@transferwise/components 0.0.0-experimental-4658255 → 0.0.0-experimental-07a2614
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/build/inputs/SelectInput.js +2 -41
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +2 -41
- package/build/inputs/SelectInput.mjs.map +1 -1
- package/build/inputs/_BottomSheet.js +29 -1
- package/build/inputs/_BottomSheet.js.map +1 -1
- package/build/inputs/_BottomSheet.mjs +30 -2
- package/build/inputs/_BottomSheet.mjs.map +1 -1
- package/build/main.css +17 -5
- package/build/styles/inputs/SelectInput.css +17 -5
- package/build/styles/main.css +17 -5
- package/build/types/inputs/SelectInput.d.ts +1 -20
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/common/bottomSheet/BottomSheet.test.story.tsx +94 -0
- package/src/inputs/SelectInput.css +17 -5
- package/src/inputs/SelectInput.spec.tsx +33 -0
- package/src/inputs/SelectInput.story.tsx +0 -94
- package/src/inputs/SelectInput.test.story.tsx +83 -0
- package/src/inputs/SelectInput.tsx +1 -84
- package/src/inputs/_BottomSheet.less +16 -3
- package/src/inputs/_BottomSheet.tsx +19 -3
- package/src/main.css +17 -5
- package/src/moneyInput/MoneyInput.test.story.tsx +101 -0
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
.wds-select-input-scroll-freeze {
|
|
2
|
+
scroll-behavior: unset !important;
|
|
3
|
+
height: 100vh;
|
|
4
|
+
|
|
5
|
+
body{
|
|
6
|
+
height: 100vh;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
.np-bottom-sheet-v2-container {
|
|
2
11
|
position: relative;
|
|
3
12
|
z-index: 1060;
|
|
@@ -11,6 +20,8 @@
|
|
|
11
20
|
transition-property: opacity;
|
|
12
21
|
transition-timing-function: ease-out;
|
|
13
22
|
transition-duration: 300ms;
|
|
23
|
+
will-change: transform;
|
|
24
|
+
min-height: 100vh;
|
|
14
25
|
|
|
15
26
|
&--closed {
|
|
16
27
|
opacity: 0;
|
|
@@ -20,23 +31,25 @@
|
|
|
20
31
|
.np-bottom-sheet-v2 {
|
|
21
32
|
position: fixed;
|
|
22
33
|
inset: 0px;
|
|
23
|
-
bottom: env(
|
|
34
|
+
bottom: env(safe-area-inset-bottom, 0);
|
|
24
35
|
margin-left: var(--size-8);
|
|
25
36
|
margin-right: var(--size-8);
|
|
26
37
|
margin-top: var(--size-64);
|
|
27
38
|
display: flex;
|
|
28
39
|
flex-direction: column;
|
|
29
40
|
justify-content: flex-end;
|
|
41
|
+
height: calc(100vh - var(--size-64) - 40px);
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
.np-bottom-sheet-v2-content {
|
|
33
45
|
display: flex;
|
|
34
46
|
flex-direction: column;
|
|
35
47
|
overflow: auto;
|
|
36
|
-
border-
|
|
37
|
-
|
|
48
|
+
border-radius: var(--size-32);
|
|
49
|
+
margin-bottom: var(--size-8);
|
|
38
50
|
background-color: var(--color-background-elevated);
|
|
39
51
|
box-shadow: 0 0 40px rgb(69 71 69 / 0.2);
|
|
52
|
+
will-change: transform;
|
|
40
53
|
|
|
41
54
|
&:focus {
|
|
42
55
|
outline: none;
|
|
@@ -10,12 +10,11 @@ import { Transition } from '@headlessui/react';
|
|
|
10
10
|
import { FocusScope } from '@react-aria/focus';
|
|
11
11
|
import { ThemeProvider, useTheme } from '@wise/components-theming';
|
|
12
12
|
import { clsx } from 'clsx';
|
|
13
|
-
import { Fragment, useState } from 'react';
|
|
13
|
+
import { Fragment, useEffect, useState } from 'react';
|
|
14
14
|
|
|
15
|
-
import { CloseButton } from '../common
|
|
15
|
+
import { CloseButton , Size } from '../common';
|
|
16
16
|
import { useVirtualKeyboard } from '../common/hooks/useVirtualKeyboard';
|
|
17
17
|
import { PreventScroll } from '../common/preventScroll/PreventScroll';
|
|
18
|
-
import { Size } from '../common/propsValues/size';
|
|
19
18
|
|
|
20
19
|
export interface BottomSheetProps {
|
|
21
20
|
open: boolean;
|
|
@@ -33,6 +32,19 @@ export interface BottomSheetProps {
|
|
|
33
32
|
onCloseEnd?: () => void;
|
|
34
33
|
}
|
|
35
34
|
|
|
35
|
+
/**
|
|
36
|
+
* App pages set scroll-behavior to 'smooth' which causes mobile Safari to
|
|
37
|
+
* slow-scroll and glitch. This function temporarily disables that behaviour
|
|
38
|
+
* while the BottomSheet is open. It complements <PreventScroll />.
|
|
39
|
+
*/
|
|
40
|
+
const freezeScroll = (shouldFreeze = true) => {
|
|
41
|
+
if (shouldFreeze) {
|
|
42
|
+
document.documentElement.classList.add('wds-select-input-scroll-freeze');
|
|
43
|
+
} else {
|
|
44
|
+
document.documentElement.classList.remove('wds-select-input-scroll-freeze');
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
36
48
|
export function BottomSheet({
|
|
37
49
|
open,
|
|
38
50
|
renderTrigger,
|
|
@@ -54,6 +66,10 @@ export function BottomSheet({
|
|
|
54
66
|
},
|
|
55
67
|
});
|
|
56
68
|
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
freezeScroll(open);
|
|
71
|
+
}, [open]);
|
|
72
|
+
|
|
57
73
|
const dismiss = useDismiss(context);
|
|
58
74
|
const role = useRole(context);
|
|
59
75
|
const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, role]);
|
package/src/main.css
CHANGED
|
@@ -3524,6 +3524,13 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3524
3524
|
padding-inline-start: 8px;
|
|
3525
3525
|
padding-inline-start: var(--size-8);
|
|
3526
3526
|
}
|
|
3527
|
+
.wds-select-input-scroll-freeze {
|
|
3528
|
+
scroll-behavior: unset !important;
|
|
3529
|
+
height: 100vh;
|
|
3530
|
+
}
|
|
3531
|
+
.wds-select-input-scroll-freeze body {
|
|
3532
|
+
height: 100vh;
|
|
3533
|
+
}
|
|
3527
3534
|
.np-bottom-sheet-v2-container {
|
|
3528
3535
|
position: relative;
|
|
3529
3536
|
z-index: 1060;
|
|
@@ -3537,6 +3544,8 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3537
3544
|
transition-property: opacity;
|
|
3538
3545
|
transition-timing-function: ease-out;
|
|
3539
3546
|
transition-duration: 300ms;
|
|
3547
|
+
will-change: transform;
|
|
3548
|
+
min-height: 100vh;
|
|
3540
3549
|
}
|
|
3541
3550
|
.np-bottom-sheet-v2-backdrop--closed {
|
|
3542
3551
|
opacity: 0;
|
|
@@ -3544,7 +3553,7 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3544
3553
|
.np-bottom-sheet-v2 {
|
|
3545
3554
|
position: fixed;
|
|
3546
3555
|
inset: 0px;
|
|
3547
|
-
bottom: env(
|
|
3556
|
+
bottom: env(safe-area-inset-bottom, 0);
|
|
3548
3557
|
margin-left: 8px;
|
|
3549
3558
|
margin-left: var(--size-8);
|
|
3550
3559
|
margin-right: 8px;
|
|
@@ -3554,18 +3563,21 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3554
3563
|
display: flex;
|
|
3555
3564
|
flex-direction: column;
|
|
3556
3565
|
justify-content: flex-end;
|
|
3566
|
+
height: calc(100vh - 64px - 40px);
|
|
3567
|
+
height: calc(100vh - var(--size-64) - 40px);
|
|
3557
3568
|
}
|
|
3558
3569
|
.np-bottom-sheet-v2-content {
|
|
3559
3570
|
display: flex;
|
|
3560
3571
|
flex-direction: column;
|
|
3561
3572
|
overflow: auto;
|
|
3562
|
-
border-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3573
|
+
border-radius: 32px;
|
|
3574
|
+
border-radius: var(--size-32);
|
|
3575
|
+
margin-bottom: 8px;
|
|
3576
|
+
margin-bottom: var(--size-8);
|
|
3566
3577
|
background-color: #ffffff;
|
|
3567
3578
|
background-color: var(--color-background-elevated);
|
|
3568
3579
|
box-shadow: 0 0 40px rgba(69, 71, 69, 0.2);
|
|
3580
|
+
will-change: transform;
|
|
3569
3581
|
}
|
|
3570
3582
|
.np-bottom-sheet-v2-content:focus {
|
|
3571
3583
|
outline: none;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
import { userEvent, within } from 'storybook/test';
|
|
3
|
+
import { allModes } from '../../.storybook/modes';
|
|
4
|
+
import { lorem500 } from '../test-utils';
|
|
5
|
+
import { Field } from '../field/Field';
|
|
6
|
+
import Body from '../body';
|
|
7
|
+
import MoneyInput from './MoneyInput';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Forms/MoneyInput/tests',
|
|
11
|
+
component: MoneyInput,
|
|
12
|
+
args: {
|
|
13
|
+
amount: 1000,
|
|
14
|
+
id: 'moneyInput',
|
|
15
|
+
currencies: [
|
|
16
|
+
{
|
|
17
|
+
value: 'EUR',
|
|
18
|
+
label: 'EUR',
|
|
19
|
+
note: 'Euro',
|
|
20
|
+
currency: 'eur',
|
|
21
|
+
searchable: 'Spain, Germany, France, Austria',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
value: 'GBP',
|
|
25
|
+
label: 'GBP',
|
|
26
|
+
note: 'British pound',
|
|
27
|
+
currency: 'gbp',
|
|
28
|
+
searchable: 'England, Scotland, Wales',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
selectedCurrency: {
|
|
32
|
+
value: 'EUR',
|
|
33
|
+
label: 'EUR',
|
|
34
|
+
note: 'Euro',
|
|
35
|
+
currency: 'eur',
|
|
36
|
+
searchable: 'Spain, Germany, France, Austria',
|
|
37
|
+
},
|
|
38
|
+
searchPlaceholder: '',
|
|
39
|
+
onAmountChange: () => {},
|
|
40
|
+
onCurrencyChange: () => {},
|
|
41
|
+
},
|
|
42
|
+
tags: ['!autodocs'],
|
|
43
|
+
} satisfies Meta<typeof MoneyInput>;
|
|
44
|
+
export default meta;
|
|
45
|
+
|
|
46
|
+
type Story = StoryObj<typeof MoneyInput>;
|
|
47
|
+
|
|
48
|
+
const wait = async (duration = 500) =>
|
|
49
|
+
new Promise<void>((resolve) => {
|
|
50
|
+
setTimeout(resolve, duration);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* This test ensures that when the SelectInput is used within a scrollable page,
|
|
55
|
+
* opening the dropdown does not cause any unwanted scrolling or layout shifts.
|
|
56
|
+
* Expected preview should start with green bar at the top, with yellow section
|
|
57
|
+
* not in the viewport.
|
|
58
|
+
*
|
|
59
|
+
* NB: This test is disabled in Chromatic as there's no obvious way to control <html/> element of a snapshot.
|
|
60
|
+
*/
|
|
61
|
+
export const SmoothScrollReset: Story = {
|
|
62
|
+
decorators: [
|
|
63
|
+
(Story) => (
|
|
64
|
+
<>
|
|
65
|
+
<style>{`html { scroll-behavior: smooth; }`}</style>
|
|
66
|
+
<div>
|
|
67
|
+
<div
|
|
68
|
+
className="d-flex align-items-center justify-content-center"
|
|
69
|
+
style={{
|
|
70
|
+
backgroundColor: 'var(--color-bright-yellow)',
|
|
71
|
+
height: 400,
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
This block should not be in the viewport.
|
|
75
|
+
</div>
|
|
76
|
+
<div style={{ height: 10, backgroundColor: 'var(--color-bright-green)' }} />
|
|
77
|
+
<Field id="el1" label="Select currency">
|
|
78
|
+
<Story />
|
|
79
|
+
</Field>
|
|
80
|
+
<Body as="p">{lorem500}</Body>
|
|
81
|
+
</div>
|
|
82
|
+
</>
|
|
83
|
+
),
|
|
84
|
+
],
|
|
85
|
+
play: async ({ canvasElement }) => {
|
|
86
|
+
await wait();
|
|
87
|
+
document.documentElement.scrollTop = 400;
|
|
88
|
+
await wait();
|
|
89
|
+
const canvas = within(canvasElement);
|
|
90
|
+
const triggerButton = canvas.getByRole('combobox');
|
|
91
|
+
await userEvent.click(triggerButton);
|
|
92
|
+
},
|
|
93
|
+
globals: {
|
|
94
|
+
viewport: { value: allModes.largeMobile.viewport, isRotated: false },
|
|
95
|
+
},
|
|
96
|
+
parameters: {
|
|
97
|
+
chromatic: {
|
|
98
|
+
disableSnapshot: true,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|