@transferwise/components 0.0.0-experimental-47052c9 → 0.0.0-experimental-b2b287d

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 (149) hide show
  1. package/build/Snackbar/Snackbar.js +178 -102
  2. package/build/Snackbar/Snackbar.js.map +1 -1
  3. package/build/Snackbar/Snackbar.messages.js +14 -0
  4. package/build/Snackbar/Snackbar.messages.js.map +1 -0
  5. package/build/Snackbar/Snackbar.messages.mjs +10 -0
  6. package/build/Snackbar/Snackbar.messages.mjs.map +1 -0
  7. package/build/Snackbar/Snackbar.mjs +180 -101
  8. package/build/Snackbar/Snackbar.mjs.map +1 -1
  9. package/build/Snackbar/SnackbarContext.js.map +1 -1
  10. package/build/Snackbar/SnackbarContext.mjs.map +1 -1
  11. package/build/Snackbar/SnackbarPortal.js +12 -0
  12. package/build/Snackbar/SnackbarPortal.js.map +1 -0
  13. package/build/Snackbar/SnackbarPortal.mjs +8 -0
  14. package/build/Snackbar/SnackbarPortal.mjs.map +1 -0
  15. package/build/Snackbar/SnackbarProvider.js +24 -28
  16. package/build/Snackbar/SnackbarProvider.js.map +1 -1
  17. package/build/Snackbar/SnackbarProvider.mjs +25 -29
  18. package/build/Snackbar/SnackbarProvider.mjs.map +1 -1
  19. package/build/Snackbar/constants.js +17 -0
  20. package/build/Snackbar/constants.js.map +1 -0
  21. package/build/Snackbar/constants.mjs +11 -0
  22. package/build/Snackbar/constants.mjs.map +1 -0
  23. package/build/Snackbar/useSnackbarAutoDismiss.js +66 -0
  24. package/build/Snackbar/useSnackbarAutoDismiss.js.map +1 -0
  25. package/build/Snackbar/useSnackbarAutoDismiss.mjs +62 -0
  26. package/build/Snackbar/useSnackbarAutoDismiss.mjs.map +1 -0
  27. package/build/Snackbar/useSnackbarManager.js +153 -0
  28. package/build/Snackbar/useSnackbarManager.js.map +1 -0
  29. package/build/Snackbar/useSnackbarManager.mjs +149 -0
  30. package/build/Snackbar/useSnackbarManager.mjs.map +1 -0
  31. package/build/Snackbar/useSnackbarSwipeDismiss.js +135 -0
  32. package/build/Snackbar/useSnackbarSwipeDismiss.js.map +1 -0
  33. package/build/Snackbar/useSnackbarSwipeDismiss.mjs +131 -0
  34. package/build/Snackbar/useSnackbarSwipeDismiss.mjs.map +1 -0
  35. package/build/i18n/en.json +1 -0
  36. package/build/i18n/en.json.js +1 -0
  37. package/build/i18n/en.json.js.map +1 -1
  38. package/build/i18n/en.json.mjs +1 -0
  39. package/build/i18n/en.json.mjs.map +1 -1
  40. package/build/index.js +0 -4
  41. package/build/index.js.map +1 -1
  42. package/build/index.mjs +0 -2
  43. package/build/index.mjs.map +1 -1
  44. package/build/main.css +116 -245
  45. package/build/styles/Snackbar/Snackbar.css +117 -54
  46. package/build/styles/main.css +116 -245
  47. package/build/types/Snackbar/Snackbar.d.ts +55 -9
  48. package/build/types/Snackbar/Snackbar.d.ts.map +1 -1
  49. package/build/types/Snackbar/Snackbar.messages.d.ts +9 -0
  50. package/build/types/Snackbar/Snackbar.messages.d.ts.map +1 -0
  51. package/build/types/Snackbar/Snackbar.types.d.ts +12 -0
  52. package/build/types/Snackbar/Snackbar.types.d.ts.map +1 -0
  53. package/build/types/Snackbar/SnackbarContext.d.ts +2 -2
  54. package/build/types/Snackbar/SnackbarContext.d.ts.map +1 -1
  55. package/build/types/Snackbar/SnackbarPortal.d.ts +4 -0
  56. package/build/types/Snackbar/SnackbarPortal.d.ts.map +1 -0
  57. package/build/types/Snackbar/SnackbarProvider.d.ts +7 -0
  58. package/build/types/Snackbar/SnackbarProvider.d.ts.map +1 -1
  59. package/build/types/Snackbar/constants.d.ts +9 -0
  60. package/build/types/Snackbar/constants.d.ts.map +1 -0
  61. package/build/types/Snackbar/index.d.ts +1 -1
  62. package/build/types/Snackbar/index.d.ts.map +1 -1
  63. package/build/types/Snackbar/useSnackbar.d.ts +1 -1
  64. package/build/types/Snackbar/useSnackbar.d.ts.map +1 -1
  65. package/build/types/Snackbar/useSnackbarAutoDismiss.d.ts +13 -0
  66. package/build/types/Snackbar/useSnackbarAutoDismiss.d.ts.map +1 -0
  67. package/build/types/Snackbar/useSnackbarManager.d.ts +20 -0
  68. package/build/types/Snackbar/useSnackbarManager.d.ts.map +1 -0
  69. package/build/types/Snackbar/useSnackbarSwipeDismiss.d.ts +22 -0
  70. package/build/types/Snackbar/useSnackbarSwipeDismiss.d.ts.map +1 -0
  71. package/build/types/index.d.ts +1 -5
  72. package/build/types/index.d.ts.map +1 -1
  73. package/build/types/test-utils/index.d.ts +2 -0
  74. package/build/types/test-utils/index.d.ts.map +1 -1
  75. package/package.json +3 -3
  76. package/src/FlowNavigation/_stories/FlowNavigation.CriticalBanner.docs.mdx +66 -0
  77. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.story.tsx +2 -0
  78. package/src/Snackbar/Snackbar.css +117 -54
  79. package/src/Snackbar/Snackbar.less +139 -60
  80. package/src/Snackbar/Snackbar.messages.ts +9 -0
  81. package/src/Snackbar/Snackbar.test.tsx +989 -119
  82. package/src/Snackbar/Snackbar.tsx +208 -93
  83. package/src/Snackbar/Snackbar.types.ts +17 -0
  84. package/src/Snackbar/SnackbarContext.ts +2 -2
  85. package/src/Snackbar/SnackbarPortal.tsx +8 -0
  86. package/src/Snackbar/SnackbarProvider.test.tsx +783 -0
  87. package/src/Snackbar/SnackbarProvider.tsx +27 -19
  88. package/src/Snackbar/_stories/Snackbar.accessibility.docs.mdx +58 -0
  89. package/src/Snackbar/_stories/Snackbar.rtl.test.story.tsx +16 -8
  90. package/src/Snackbar/_stories/Snackbar.story.tsx +388 -61
  91. package/src/Snackbar/_stories/Snackbar.test.story.tsx +171 -47
  92. package/src/Snackbar/constants.ts +10 -0
  93. package/src/Snackbar/index.ts +1 -1
  94. package/src/Snackbar/useSnackbarAutoDismiss.ts +74 -0
  95. package/src/Snackbar/useSnackbarManager.ts +169 -0
  96. package/src/Snackbar/useSnackbarSwipeDismiss.ts +169 -0
  97. package/src/i18n/en.json +1 -0
  98. package/src/index.ts +1 -14
  99. package/src/main.css +116 -245
  100. package/src/main.less +0 -2
  101. package/build/CardContainer/CardContainer.js +0 -34
  102. package/build/CardContainer/CardContainer.js.map +0 -1
  103. package/build/CardContainer/CardContainer.mjs +0 -30
  104. package/build/CardContainer/CardContainer.mjs.map +0 -1
  105. package/build/CardWidget/CardWidget.js +0 -98
  106. package/build/CardWidget/CardWidget.js.map +0 -1
  107. package/build/CardWidget/CardWidget.mjs +0 -94
  108. package/build/CardWidget/CardWidget.mjs.map +0 -1
  109. package/build/CardWidget/CardWidgetAction.js +0 -73
  110. package/build/CardWidget/CardWidgetAction.js.map +0 -1
  111. package/build/CardWidget/CardWidgetAction.mjs +0 -68
  112. package/build/CardWidget/CardWidgetAction.mjs.map +0 -1
  113. package/build/styles/CardContainer/CardContainer.css +0 -108
  114. package/build/styles/CardWidget/CardWidget.css +0 -84
  115. package/build/types/CardContainer/CardContainer.d.ts +0 -8
  116. package/build/types/CardContainer/CardContainer.d.ts.map +0 -1
  117. package/build/types/CardContainer/CardContainer.types.d.ts +0 -53
  118. package/build/types/CardContainer/CardContainer.types.d.ts.map +0 -1
  119. package/build/types/CardContainer/_stories/helpers.d.ts +0 -3
  120. package/build/types/CardContainer/_stories/helpers.d.ts.map +0 -1
  121. package/build/types/CardContainer/index.d.ts +0 -3
  122. package/build/types/CardContainer/index.d.ts.map +0 -1
  123. package/build/types/CardWidget/CardWidget.d.ts +0 -10
  124. package/build/types/CardWidget/CardWidget.d.ts.map +0 -1
  125. package/build/types/CardWidget/CardWidget.types.d.ts +0 -55
  126. package/build/types/CardWidget/CardWidget.types.d.ts.map +0 -1
  127. package/build/types/CardWidget/CardWidgetAction.d.ts +0 -54
  128. package/build/types/CardWidget/CardWidgetAction.d.ts.map +0 -1
  129. package/build/types/CardWidget/index.d.ts +0 -4
  130. package/build/types/CardWidget/index.d.ts.map +0 -1
  131. package/src/CardContainer/CardContainer.css +0 -108
  132. package/src/CardContainer/CardContainer.less +0 -171
  133. package/src/CardContainer/CardContainer.test.tsx +0 -150
  134. package/src/CardContainer/CardContainer.tsx +0 -51
  135. package/src/CardContainer/CardContainer.types.ts +0 -60
  136. package/src/CardContainer/_stories/CardContainer.story.tsx +0 -167
  137. package/src/CardContainer/_stories/CardContainer.test.story.tsx +0 -103
  138. package/src/CardContainer/_stories/helpers.tsx +0 -50
  139. package/src/CardContainer/index.ts +0 -6
  140. package/src/CardWidget/CardWidget.css +0 -84
  141. package/src/CardWidget/CardWidget.less +0 -110
  142. package/src/CardWidget/CardWidget.test.tsx +0 -222
  143. package/src/CardWidget/CardWidget.tsx +0 -83
  144. package/src/CardWidget/CardWidget.types.ts +0 -63
  145. package/src/CardWidget/CardWidgetAction.tsx +0 -128
  146. package/src/CardWidget/_stories/CardWidget.story.tsx +0 -238
  147. package/src/CardWidget/_stories/CardWidget.test.story.tsx +0 -350
  148. package/src/CardWidget/index.ts +0 -3
  149. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.docs.mdx +0 -122
@@ -0,0 +1,169 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+
3
+ import { SNACKBAR_SWIPE_DISMISS_THRESHOLD } from './constants';
4
+
5
+ const DISMISS_CLASS = 'wds-Snackbar--swipe-dismiss';
6
+ const SETTLE_CLASS = 'wds-Snackbar--swipe-settle';
7
+
8
+ type SwipePointer = {
9
+ id: number;
10
+ target: Element;
11
+ startX: number;
12
+ startY: number;
13
+ threshold: number;
14
+ };
15
+
16
+ /**
17
+ * Captures one primary pointer and follows downward, mostly vertical movement without re-rendering.
18
+ * Release dismisses at half the surface height; shorter/cancelled gestures settle back into place.
19
+ * The outer wrapper moves independently of entry/exit motion, and a committed swipe consumes its
20
+ * follow-up click so dragging from the action cannot activate it.
21
+ */
22
+ const useSnackbarSwipeDismiss = ({
23
+ onDismissRequest,
24
+ onSwipeChange,
25
+ visible,
26
+ }: {
27
+ onDismissRequest: () => void;
28
+ /** Reports when a gesture starts and ends so auto-dismiss can pause beneath the pointer. */
29
+ onSwipeChange: (swiping: boolean) => void;
30
+ visible: boolean;
31
+ }) => {
32
+ const containerRef = useRef<HTMLDivElement>(null);
33
+ const pointerRef = useRef<SwipePointer | null>(null);
34
+ const suppressClick = useRef(false);
35
+
36
+ const clearSwipePosition = useCallback(() => {
37
+ const pointer = pointerRef.current;
38
+ pointerRef.current = null;
39
+ if (pointer) {
40
+ if (pointer.target.hasPointerCapture?.(pointer.id)) {
41
+ pointer.target.releasePointerCapture(pointer.id);
42
+ }
43
+ onSwipeChange(false);
44
+ }
45
+ suppressClick.current = false;
46
+ containerRef.current?.classList.remove(DISMISS_CLASS, SETTLE_CLASS);
47
+ containerRef.current?.style.removeProperty('transform');
48
+ }, [onSwipeChange]);
49
+
50
+ const handlePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
51
+ if (event.button !== 0 || !event.isPrimary || pointerRef.current) {
52
+ return;
53
+ }
54
+
55
+ clearSwipePosition();
56
+ const target = event.target as Element;
57
+ target.setPointerCapture?.(event.pointerId);
58
+ pointerRef.current = {
59
+ id: event.pointerId,
60
+ target,
61
+ startX: event.clientX,
62
+ startY: event.clientY,
63
+ threshold: event.currentTarget.offsetHeight * SNACKBAR_SWIPE_DISMISS_THRESHOLD,
64
+ };
65
+ onSwipeChange(true);
66
+ };
67
+
68
+ const handlePointerMove = (event: React.PointerEvent<HTMLDivElement>) => {
69
+ const pointer = pointerRef.current;
70
+ if (pointer?.id !== event.pointerId) {
71
+ return;
72
+ }
73
+
74
+ const offsetY = event.clientY - pointer.startY;
75
+ const offsetX = event.clientX - pointer.startX;
76
+ if (offsetY > 0 && offsetY > Math.abs(offsetX)) {
77
+ containerRef.current?.style.setProperty('transform', `translateY(${offsetY}px)`);
78
+ } else {
79
+ containerRef.current?.style.removeProperty('transform');
80
+ }
81
+ };
82
+
83
+ const handlePointerUp = (event: React.PointerEvent<HTMLDivElement>) => {
84
+ const pointer = pointerRef.current;
85
+ if (pointer?.id !== event.pointerId) {
86
+ return;
87
+ }
88
+
89
+ const offsetY = event.clientY - pointer.startY;
90
+ const offsetX = event.clientX - pointer.startX;
91
+ const container = containerRef.current;
92
+ const bounds = pointer.target.closest('a, button')?.getBoundingClientRect();
93
+ clearSwipePosition();
94
+
95
+ if (offsetY >= pointer.threshold && offsetY > Math.abs(offsetX)) {
96
+ if (container) {
97
+ // Include wrapper padding and the safe area, not only the surface, to clear the viewport.
98
+ container.classList.add(DISMISS_CLASS);
99
+ container.style.setProperty(
100
+ 'transform',
101
+ `translateY(${Math.max(offsetY, container.offsetHeight)}px)`,
102
+ );
103
+ }
104
+ suppressClick.current = true;
105
+ onDismissRequest();
106
+ } else {
107
+ // Capture retargets clicks to the pressed control even when released outside it.
108
+ suppressClick.current =
109
+ !!bounds &&
110
+ (offsetX !== 0 || offsetY !== 0) &&
111
+ (event.clientX < bounds.left ||
112
+ event.clientX > bounds.right ||
113
+ event.clientY < bounds.top ||
114
+ event.clientY > bounds.bottom);
115
+ container?.classList.add(SETTLE_CLASS);
116
+ }
117
+ };
118
+
119
+ const handlePointerCancel = useCallback(
120
+ (event: Pick<PointerEvent, 'pointerId'>) => {
121
+ if (pointerRef.current?.id !== event.pointerId) {
122
+ return;
123
+ }
124
+
125
+ clearSwipePosition();
126
+ containerRef.current?.classList.add(SETTLE_CLASS);
127
+ },
128
+ [clearSwipePosition],
129
+ );
130
+
131
+ useEffect(() => {
132
+ if (visible) {
133
+ clearSwipePosition();
134
+ } else if (pointerRef.current) {
135
+ // An exit starting mid-gesture (timeout, Escape, replacement) ends it without dismissing again.
136
+ handlePointerCancel({ pointerId: pointerRef.current.id });
137
+ }
138
+ }, [visible, clearSwipePosition, handlePointerCancel]);
139
+
140
+ useEffect(() => {
141
+ // Removed descendants report capture loss on their document, not the Snackbar surface.
142
+ const ownerDocument = containerRef.current?.ownerDocument;
143
+ ownerDocument?.addEventListener('lostpointercapture', handlePointerCancel);
144
+ return () => {
145
+ ownerDocument?.removeEventListener('lostpointercapture', handlePointerCancel);
146
+ clearSwipePosition();
147
+ };
148
+ }, [clearSwipePosition, handlePointerCancel]);
149
+
150
+ const handleClickCapture = (event: React.MouseEvent<HTMLDivElement>) => {
151
+ if (suppressClick.current && event.detail > 0) {
152
+ suppressClick.current = false;
153
+ event.preventDefault();
154
+ event.stopPropagation();
155
+ }
156
+ };
157
+
158
+ return {
159
+ clearSwipePosition,
160
+ containerRef,
161
+ handleClickCapture,
162
+ handlePointerCancel,
163
+ handlePointerDown,
164
+ handlePointerMove,
165
+ handlePointerUp,
166
+ };
167
+ };
168
+
169
+ export default useSnackbarSwipeDismiss;
package/src/i18n/en.json CHANGED
@@ -38,6 +38,7 @@
38
38
  "neptune.PhoneNumberInput.phoneNumberPrefix": "Prefix",
39
39
  "neptune.Select.searchPlaceholder": "Search...",
40
40
  "neptune.SelectInput.noResultsFound": "No results found",
41
+ "neptune.Snackbar.escapeDismissHint": "Press Escape to dismiss.",
41
42
  "neptune.StatusIcon.iconLabel.error": "Error:",
42
43
  "neptune.StatusIcon.iconLabel.information": "Information:",
43
44
  "neptune.StatusIcon.iconLabel.pending": "Pending:",
package/src/index.ts CHANGED
@@ -4,17 +4,6 @@
4
4
  * Types
5
5
  */
6
6
  export type { ContainerProps } from './Container';
7
- export type {
8
- CardContainerProps,
9
- CardContainerSpotlight,
10
- CardContainerPadding,
11
- } from './CardContainer';
12
- export type {
13
- CardWidgetProps,
14
- CardWidgetHeader,
15
- CardWidgetTitleAction,
16
- CardWidgetActionButton,
17
- } from './CardWidget';
18
7
  export type { LogoProps, LogoSize, LogoAssetName } from './Logo';
19
8
  export type { FlowNavigationProps, CriticalBannerLegacyData } from './FlowNavigation';
20
9
  export type { AccordionItem, AccordionProps } from './Accordion';
@@ -146,7 +135,7 @@ export type {
146
135
  SelectProps,
147
136
  } from './_deprecated/Select';
148
137
  export type { SlidingPanelProps } from './SlidingPanel';
149
- export type { SnackbarProps, SnackbarProviderProps } from './Snackbar';
138
+ export type { SnackbarCreationProps, SnackbarProviderProps } from './Snackbar';
150
139
  export type { SnackbarContextType } from './Snackbar/SnackbarContext';
151
140
  export type { StatusIconProps, StatusIconSentiment } from './StatusIcon';
152
141
  export type { StickyProps } from './Sticky';
@@ -229,8 +218,6 @@ export { default as Chevron } from './Chevron';
229
218
  export { Chip, default as Chips } from './Chips';
230
219
  export { default as CircularButton } from './CircularButton';
231
220
  export { default as Container } from './Container';
232
- export { default as CardContainer } from './CardContainer';
233
- export { default as CardWidget } from './CardWidget';
234
221
  export { default as Option } from './common/Option';
235
222
  export { default as BottomSheet } from './common/BottomSheet';
236
223
  export { default as BaseCard } from './common/BaseCard';
package/src/main.css CHANGED
@@ -26203,198 +26203,6 @@ a[data-toggle="tooltip"] {
26203
26203
  .wds-container--fluid {
26204
26204
  max-inline-size: var(--wds-container-width-fluid);
26205
26205
  }
26206
- .wds-card-container {
26207
- --CardContainer-shadow: var(--CardContainer-theme-shadow, none);
26208
- --CardContainer-background-color: var(--color-background-screen);
26209
- --CardContainer-border-color: var(--color-border-neutral);
26210
- --CardContainer-border-radius: var(--radius-large);
26211
- --CardContainer-padding-block: var(--size-8);
26212
- --CardContainer-padding-inline: var(--size-8);
26213
- background-color: var(--CardContainer-background-color);
26214
- border: 1px solid var(--CardContainer-border-color);
26215
- border-radius: var(--CardContainer-border-radius);
26216
- box-sizing: border-box;
26217
- display: flex;
26218
- flex-direction: column;
26219
- padding-block: var(--CardContainer-padding-block);
26220
- padding-inline: var(--CardContainer-padding-inline);
26221
- inline-size: 100%;
26222
- }
26223
- @media (min-width: 840px) {
26224
- .wds-card-container {
26225
- --CardContainer-padding-block: var(--size-16);
26226
- --CardContainer-padding-inline: var(--size-16);
26227
- }
26228
- }
26229
- .wds-card-container--padding-none {
26230
- --CardContainer-padding-block: 0px;
26231
- --CardContainer-padding-inline: 0px;
26232
- overflow: clip;
26233
- }
26234
- .wds-card-container--active {
26235
- --CardContainer-background-color: var(--color-background-elevated);
26236
- --CardContainer-border-color: color-mix(in srgb, var(--color-border-neutral) 25%, transparent);
26237
- box-shadow: var(--CardContainer-shadow);
26238
- }
26239
- .wds-card-container--inactive {
26240
- --CardContainer-background-color: color-mix(in srgb, var(--color-background-neutral) 25%, transparent);
26241
- border-width: 0;
26242
- padding-block: calc(var(--CardContainer-padding-block) + 1px);
26243
- padding-inline: calc(var(--CardContainer-padding-inline) + 1px);
26244
- position: relative;
26245
- }
26246
- .wds-card-container--interactive:has(
26247
- > a[href]:hover,
26248
- > button:enabled:hover,
26249
- > a[href]:focus-visible,
26250
- > button:enabled:focus-visible
26251
- ).wds-card-container--active {
26252
- --CardContainer-border-color: color-mix(in srgb, var(--color-border-neutral) 75%, transparent);
26253
- }
26254
- .wds-card-container--interactive:has(
26255
- > a[href]:hover,
26256
- > button:enabled:hover,
26257
- > a[href]:focus-visible,
26258
- > button:enabled:focus-visible
26259
- ).wds-card-container--inactive {
26260
- --CardContainer-background-color: color-mix(in srgb, var(--color-background-neutral-hover) 25%, transparent);
26261
- }
26262
- .wds-card-container--interactive:has(> a[href]:active, > button:enabled:active).wds-card-container--active {
26263
- --CardContainer-border-color: var(--color-border-neutral);
26264
- }
26265
- .wds-card-container--interactive:has(> a[href]:active, > button:enabled:active).wds-card-container--inactive {
26266
- --CardContainer-background-color: color-mix(in srgb, var(--color-background-neutral-active) 25%, transparent);
26267
- }
26268
- .wds-card-container__border {
26269
- container-type: size;
26270
- inset: 0;
26271
- pointer-events: none;
26272
- position: absolute;
26273
- }
26274
- .wds-card-container__border svg {
26275
- display: block;
26276
- block-size: 100%;
26277
- inline-size: 100%;
26278
- }
26279
- .wds-card-container__border rect {
26280
- --CardContainer-border-dash-size: calc(var(--size-12) * 0.5);
26281
- --CardContainer-border-stroke-radius: calc(min(var(--CardContainer-border-radius), 50cqh, 50cqw) - 0.5px);
26282
- fill: none;
26283
- block-size: calc(100% - 1px);
26284
- rx: var(--CardContainer-border-stroke-radius);
26285
- ry: var(--CardContainer-border-stroke-radius);
26286
- stroke: var(--color-border-neutral);
26287
- stroke-dasharray: var(--CardContainer-border-dash-size) var(--CardContainer-border-dash-size);
26288
- inline-size: calc(100% - 1px);
26289
- x: 0.5px;
26290
- y: 0.5px;
26291
- }
26292
- /**
26293
- * The active spotlight's resting shadow, only designed for the light themes. Set on every theme
26294
- * root, as a nested ThemeProvider renders its own, so a card follows its nearest theme: a dark or
26295
- * green provider inside a light one turns the shadow off.
26296
- *
26297
- * There is no shadow or elevation token in @transferwise/neptune-tokens, so the value is
26298
- * component-scoped for now, the way PromoCard scopes `--Card-box-shadow`. It is the "Card Active
26299
- * shadow" effect style from Figma: `#0e0f0c` at 4%, kept literal so it doesn't drift with a
26300
- * theme's tokens. Collapses to a token reference once one is minted.
26301
- */
26302
- .np-theme-personal {
26303
- --CardContainer-theme-shadow: 0 2px 12px rgba(14, 15, 12, 0.04), 0 2px 32px rgba(14, 15, 12, 0.04);
26304
- }
26305
- .np-theme-personal.np-theme-personal--dark,
26306
- .np-theme-personal.np-theme-personal--bright-green,
26307
- .np-theme-personal.np-theme-personal--forest-green,
26308
- .np-theme-personal.np-theme-business--dark,
26309
- .np-theme-personal.np-theme-business--bright-green,
26310
- .np-theme-personal.np-theme-business--forest-green,
26311
- .np-theme-personal.np-theme-platform--forest-green {
26312
- --CardContainer-theme-shadow: none;
26313
- }
26314
- .wds-card-widget {
26315
- --CardWidget-inset: var(--size-8);
26316
- --CardWidget-header-spacing: var(--size-8);
26317
- --CardWidget-actions-gap: var(--size-8);
26318
- }
26319
- .wds-card-widget__header {
26320
- align-items: center;
26321
- -moz-column-gap: var(--size-24);
26322
- column-gap: var(--size-24);
26323
- container-type: inline-size;
26324
- display: flex;
26325
- flex-wrap: wrap;
26326
- padding-inline-start: var(--CardWidget-inset);
26327
- row-gap: var(--size-8);
26328
- }
26329
- .wds-card-widget__header + .wds-card-widget__content {
26330
- margin-block-start: var(--CardWidget-header-spacing);
26331
- }
26332
- .wds-card-widget__title {
26333
- align-items: center;
26334
- color: var(--color-content-secondary);
26335
- display: grid;
26336
- flex: 1 1 0;
26337
- margin: 0;
26338
- min-block-size: var(--size-32);
26339
- }
26340
- @container (width <= 360px) {
26341
- .wds-card-widget__title {
26342
- flex-basis: auto;
26343
- }
26344
- }
26345
- .wds-card-widget__title-link.np-link {
26346
- color: inherit;
26347
- display: inline;
26348
- font: inherit;
26349
- justify-self: start;
26350
- letter-spacing: inherit;
26351
- text-align: start;
26352
- -webkit-text-decoration: none;
26353
- text-decoration: none;
26354
- }
26355
- .wds-card-widget__title-link.np-link:hover,
26356
- .wds-card-widget__title-link.np-link:focus-visible {
26357
- -webkit-text-decoration: underline;
26358
- text-decoration: underline;
26359
- }
26360
- .wds-card-widget__title-link.np-link .tw-icon {
26361
- display: inline-block;
26362
- vertical-align: text-bottom;
26363
- }
26364
- .wds-card-widget__title-link.np-link .wds-card-widget__title-chevron {
26365
- white-space: nowrap;
26366
- }
26367
- .wds-card-widget__title-link.np-link .wds-card-widget__title-chevron .tw-icon {
26368
- margin: 0;
26369
- }
26370
- .wds-card-widget__actions {
26371
- align-self: start;
26372
- align-items: center;
26373
- display: flex;
26374
- flex: none;
26375
- gap: var(--CardWidget-actions-gap);
26376
- }
26377
- .wds-card-widget--with-header .wds-card-widget__content {
26378
- padding-inline: var(--CardWidget-inset);
26379
- }
26380
- .wds-card-widget--interactive:has(
26381
- .wds-card-widget__title-link:hover,
26382
- .wds-card-widget__title-link:focus-visible
26383
- ).wds-card-container--active {
26384
- --CardContainer-border-color: color-mix(in srgb, var(--color-border-neutral) 75%, transparent);
26385
- }
26386
- .wds-card-widget--interactive:has(
26387
- .wds-card-widget__title-link:hover,
26388
- .wds-card-widget__title-link:focus-visible
26389
- ).wds-card-container--inactive {
26390
- --CardContainer-background-color: color-mix(in srgb, var(--color-background-neutral-hover) 25%, transparent);
26391
- }
26392
- .wds-card-widget--interactive:has(.wds-card-widget__title-link:active).wds-card-container--active {
26393
- --CardContainer-border-color: var(--color-border-neutral);
26394
- }
26395
- .wds-card-widget--interactive:has(.wds-card-widget__title-link:active).wds-card-container--inactive {
26396
- --CardContainer-background-color: color-mix(in srgb, var(--color-background-neutral-active) 25%, transparent);
26397
- }
26398
26206
  .critical-comms {
26399
26207
  border-radius: var(--radius-medium);
26400
26208
  overflow: hidden;
@@ -31514,75 +31322,138 @@ button.np-link {
31514
31322
  [dir="rtl"] .np-theme-personal .sliding-panel.sliding-panel--border-left {
31515
31323
  box-shadow: inset 1px 0 0 0 var(--color-border-neutral);
31516
31324
  }
31517
- .snackbar {
31518
- text-align: center;
31325
+ .wds-Snackbar {
31326
+ display: flex;
31327
+ justify-content: center;
31328
+ box-sizing: border-box;
31329
+ padding-inline: var(--size-16);
31330
+ padding-block-end: calc(var(--size-16) + env(safe-area-inset-bottom));
31519
31331
  position: fixed;
31520
31332
  inset-block-end: 0;
31521
- inset-inline-start: 0;
31522
- inset-inline-end: 0;
31333
+ inset-inline: 0;
31523
31334
  z-index: 1060;
31524
31335
  }
31525
- .snackbar__text {
31526
- background: #37517e;
31527
- color: #ffffff;
31528
- display: inline-flex;
31529
- border-radius: 2px;
31530
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
31531
- align-items: center;
31532
- justify-content: space-between;
31336
+ @media (min-width: 600px) {
31337
+ .wds-Snackbar {
31338
+ padding-block-end: var(--size-24);
31339
+ }
31340
+ }
31341
+ .wds-Snackbar--swipe-dismiss {
31342
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
31343
+ }
31344
+ .wds-Snackbar--swipe-settle {
31345
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(0, 0, 0, 1);
31346
+ }
31347
+ .wds-Snackbar-container {
31348
+ --Prompt-border-radius: var(--radius-medium);
31349
+ --Prompt-gap: var(--size-8);
31350
+ --Prompt-padding-x: var(--size-12);
31351
+ --Prompt-padding-y: var(--size-12);
31352
+ box-sizing: border-box;
31353
+ max-inline-size: 480px;
31533
31354
  text-align: start;
31534
- font-size: var(--wds-font-size-body);
31535
- margin-block: 0;
31536
- margin-inline: var(--size-16);
31537
- padding-block: var(--size-8);
31538
- padding-inline: var(--size-16);
31539
- inline-size: calc(100% - var(--size-32));
31540
- transition: 400ms cubic-bezier(0.215, 0.61, 0.355, 1);
31355
+ cursor: grab;
31356
+ touch-action: pan-x pinch-zoom;
31541
31357
  }
31542
- .np-theme-personal .snackbar__text {
31543
- box-shadow: 0 2px 4px 0 rgba(69, 71, 69, 0.35);
31544
- position: relative;
31545
- background: var(--color-contrast-theme);
31546
- border-radius: var(--radius-small);
31547
- color: var(--color-contrast-overlay);
31358
+ .wds-Snackbar-container .wds-prompt__content-wrapper--with-dismiss {
31359
+ grid-template-columns: auto minmax(0, 1fr);
31548
31360
  }
31549
- .np-theme-personal .snackbar__text::after {
31550
- display: block;
31551
- border-radius: inherit;
31552
- block-size: 100%;
31553
- inline-size: 100%;
31554
- content: "";
31555
- position: absolute;
31556
- inset-inline-start: 0;
31557
- inset-block-start: 0;
31558
- z-index: -1;
31559
- background-color: var(--color-background-neutral);
31361
+ @media (min-width: 600px) {
31362
+ .wds-Snackbar-container .wds-prompt__content-wrapper--with-dismiss {
31363
+ grid-template-columns: auto minmax(0, 1fr) auto;
31364
+ }
31560
31365
  }
31561
- .np-theme-personal--dark .snackbar__text,
31562
- .np-theme-personal--forest-green .snackbar__text {
31563
- box-shadow: none;
31366
+ .wds-Snackbar-container .wds-prompt__media-wrapper {
31367
+ display: flex;
31368
+ align-items: center;
31369
+ min-block-size: max(var(--size-32), 1lh);
31370
+ padding-block-start: 0;
31371
+ color: var(--color-sentiment-content-primary);
31372
+ }
31373
+ .wds-Snackbar-container .wds-prompt__media-wrapper:has(+ .wds-Snackbar__content .wds-Snackbar__action) {
31374
+ min-block-size: max(var(--size-32), calc(1lh + var(--size-5) * 2));
31375
+ }
31376
+ .wds-Snackbar__media-asset {
31377
+ display: flex;
31378
+ }
31379
+ .wds-Snackbar__media-asset svg {
31380
+ inline-size: var(--size-24);
31381
+ block-size: var(--size-24);
31382
+ }
31383
+ .wds-Snackbar__process-indicator .process-circle {
31384
+ stroke: currentColor;
31385
+ }
31386
+ .wds-Snackbar-container .wds-prompt__dismiss {
31387
+ display: none;
31388
+ align-self: flex-start;
31389
+ margin-block-start: calc(var(--size-4) - 1px);
31564
31390
  }
31565
31391
  @media (min-width: 600px) {
31566
- .snackbar__text {
31567
- inline-size: auto;
31568
- max-inline-size: 600px;
31392
+ .wds-Snackbar-container .wds-prompt__dismiss {
31393
+ display: flex;
31569
31394
  }
31570
31395
  }
31571
- .snackbar__text__action {
31396
+ .wds-Snackbar__action {
31572
31397
  flex-shrink: 0;
31573
- margin-inline-start: var(--size-16);
31574
31398
  }
31575
- .snackbar__text-container-enter,
31576
- .snackbar__text-container-exit {
31577
- transform: translateY(calc(100% + 10px));
31399
+ .wds-Snackbar__content {
31400
+ display: flex;
31401
+ align-items: flex-start;
31402
+ gap: var(--size-8);
31403
+ flex: 1 0 0;
31404
+ min-block-size: var(--size-32);
31405
+ min-inline-size: 0;
31578
31406
  }
31579
- .snackbar__text-container-enter-active {
31580
- transform: translateY(-16px);
31581
- transform: translateY(calc(-16px - env(safe-area-inset-bottom)));
31407
+ .wds-Snackbar__message {
31408
+ display: flex;
31409
+ flex-direction: column;
31410
+ justify-content: center;
31411
+ inline-size: auto;
31412
+ flex: 1 0 0;
31413
+ min-inline-size: 0;
31414
+ align-self: stretch;
31582
31415
  }
31583
- @media (min-width: 600px) {
31584
- .snackbar__text-container-enter-active {
31585
- transform: translateY(-24px);
31416
+ .wds-Snackbar__body {
31417
+ display: block;
31418
+ }
31419
+ .wds-Snackbar-container-appear,
31420
+ .wds-Snackbar-container-enter {
31421
+ opacity: 0;
31422
+ transform: translateY(80px) scale(0.5);
31423
+ }
31424
+ .wds-Snackbar-container-appear-active,
31425
+ .wds-Snackbar-container-enter-active {
31426
+ opacity: 1;
31427
+ transform: translateY(0) scale(1);
31428
+ transition: opacity 150ms linear, transform var(--Snackbar-enter-duration) cubic-bezier(0, 0, 0, 1);
31429
+ }
31430
+ .wds-Snackbar-container-exit {
31431
+ opacity: 1;
31432
+ transform: translateY(0) scale(1);
31433
+ }
31434
+ .wds-Snackbar-container-exit-active {
31435
+ opacity: 0;
31436
+ transform: translateY(80px) scale(0.5);
31437
+ transition: opacity 50ms linear 50ms, transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
31438
+ }
31439
+ @media (prefers-reduced-motion: reduce) {
31440
+ .wds-Snackbar--swipe-dismiss,
31441
+ .wds-Snackbar--swipe-settle {
31442
+ transition: none;
31443
+ }
31444
+ .wds-Snackbar-container-appear,
31445
+ .wds-Snackbar-container-appear-active,
31446
+ .wds-Snackbar-container-enter,
31447
+ .wds-Snackbar-container-enter-active,
31448
+ .wds-Snackbar-container-exit {
31449
+ opacity: 1;
31450
+ transform: none;
31451
+ transition: none;
31452
+ }
31453
+ .wds-Snackbar-container-exit-active {
31454
+ opacity: 0;
31455
+ transform: none;
31456
+ transition: none;
31586
31457
  }
31587
31458
  }
31588
31459
  .status-circle.negative,
package/src/main.less CHANGED
@@ -4,8 +4,6 @@
4
4
  @import "./PocketSurface/PocketSurface.less";
5
5
 
6
6
  @import "./Container/Container.less";
7
- @import "./CardContainer/CardContainer.less";
8
- @import "./CardWidget/CardWidget.less";
9
7
  @import "./_deprecated/CriticalBanner/CriticalCommsBanner.less";
10
8
  @import "./Accordion/Accordion.less";
11
9
  @import "./_deprecated/ActionButton/ActionButton.less";
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var clsx = require('clsx');
6
- var React = require('react');
7
- var jsxRuntime = require('react/jsx-runtime');
8
-
9
- const CardContainer = /*#__PURE__*/React.forwardRef(({
10
- spotlight,
11
- padding = 'md',
12
- interactive = false,
13
- children,
14
- as: Element = 'section',
15
- className,
16
- ...props
17
- }, ref) => {
18
- return /*#__PURE__*/jsxRuntime.jsxs(Element, {
19
- ref: ref,
20
- className: clsx.clsx('wds-card-container', spotlight && `wds-card-container--${spotlight}`, padding === 'none' && 'wds-card-container--padding-none', interactive && 'wds-card-container--interactive', className),
21
- ...props,
22
- children: [children, spotlight === 'inactive' && /*#__PURE__*/jsxRuntime.jsx("span", {
23
- "aria-hidden": "true",
24
- className: "wds-card-container__border",
25
- children: /*#__PURE__*/jsxRuntime.jsx("svg", {
26
- children: /*#__PURE__*/jsxRuntime.jsx("rect", {})
27
- })
28
- })]
29
- });
30
- });
31
- CardContainer.displayName = 'CardContainer';
32
-
33
- exports.default = CardContainer;
34
- //# sourceMappingURL=CardContainer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CardContainer.js","sources":["../../src/CardContainer/CardContainer.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport { forwardRef } from 'react';\n\nimport type { CardContainerProps } from './CardContainer.types';\n\n/**\n * A bounded surface that groups related content. It has no slots of its own: children are stacked\n * with no gap between them. For a card with a title and actions, use `CardWidget`.\n */\nconst CardContainer = forwardRef<HTMLElement, CardContainerProps>(\n (\n {\n spotlight,\n padding = 'md',\n interactive = false,\n children,\n as: Element = 'section',\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <Element\n ref={ref as React.Ref<HTMLElement & HTMLDivElement>}\n className={clsx(\n 'wds-card-container',\n spotlight && `wds-card-container--${spotlight}`,\n padding === 'none' && 'wds-card-container--padding-none',\n interactive && 'wds-card-container--interactive',\n className,\n )}\n {...props}\n >\n {children}\n\n {spotlight === 'inactive' && (\n <span aria-hidden=\"true\" className=\"wds-card-container__border\">\n <svg>\n <rect />\n </svg>\n </span>\n )}\n </Element>\n );\n },\n);\n\nCardContainer.displayName = 'CardContainer';\n\nexport default CardContainer;\n"],"names":["CardContainer","forwardRef","spotlight","padding","interactive","children","as","Element","className","props","ref","_jsxs","clsx","_jsx","displayName"],"mappings":";;;;;;;;AASA,MAAMA,aAAa,gBAAGC,gBAAU,CAC9B,CACE;EACEC,SAAS;AACTC,EAAAA,OAAO,GAAG,IAAI;AACdC,EAAAA,WAAW,GAAG,KAAK;EACnBC,QAAQ;EACRC,EAAE,EAAEC,OAAO,GAAG,SAAS;EACvBC,SAAS;EACT,GAAGC;AAAK,CACT,EACDC,GAAG,KACD;EACF,oBACEC,eAAA,CAACJ,OAAO,EAAA;AACNG,IAAAA,GAAG,EAAEA,GAA+C;IACpDF,SAAS,EAAEI,SAAI,CACb,oBAAoB,EACpBV,SAAS,IAAI,CAAA,oBAAA,EAAuBA,SAAS,CAAA,CAAE,EAC/CC,OAAO,KAAK,MAAM,IAAI,kCAAkC,EACxDC,WAAW,IAAI,iCAAiC,EAChDI,SAAS,CACT;AAAA,IAAA,GACEC,KAAK;AAAAJ,IAAAA,QAAA,GAERA,QAAQ,EAERH,SAAS,KAAK,UAAU,iBACvBW,cAAA,CAAA,MAAA,EAAA;AAAM,MAAA,aAAA,EAAY,MAAM;AAACL,MAAAA,SAAS,EAAC,4BAA4B;AAAAH,MAAAA,QAAA,eAC7DQ,cAAA,CAAA,KAAA,EAAA;QAAAR,QAAA,eACEQ,cAAA,CAAA,MAAA,EAAA,EAAK;OACF;AACP,KAAM,CACP;AAAA,GACM,CAAC;AAEd,CAAC;AAGHb,aAAa,CAACc,WAAW,GAAG,eAAe;;"}
@@ -1,30 +0,0 @@
1
- import { clsx } from 'clsx';
2
- import { forwardRef } from 'react';
3
- import { jsxs, jsx } from 'react/jsx-runtime';
4
-
5
- const CardContainer = /*#__PURE__*/forwardRef(({
6
- spotlight,
7
- padding = 'md',
8
- interactive = false,
9
- children,
10
- as: Element = 'section',
11
- className,
12
- ...props
13
- }, ref) => {
14
- return /*#__PURE__*/jsxs(Element, {
15
- ref: ref,
16
- className: clsx('wds-card-container', spotlight && `wds-card-container--${spotlight}`, padding === 'none' && 'wds-card-container--padding-none', interactive && 'wds-card-container--interactive', className),
17
- ...props,
18
- children: [children, spotlight === 'inactive' && /*#__PURE__*/jsx("span", {
19
- "aria-hidden": "true",
20
- className: "wds-card-container__border",
21
- children: /*#__PURE__*/jsx("svg", {
22
- children: /*#__PURE__*/jsx("rect", {})
23
- })
24
- })]
25
- });
26
- });
27
- CardContainer.displayName = 'CardContainer';
28
-
29
- export { CardContainer as default };
30
- //# sourceMappingURL=CardContainer.mjs.map