@wordpress/components 21.2.0 → 21.3.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.
- package/CHANGELOG.md +35 -3
- package/CONTRIBUTING.md +20 -0
- package/build/border-box-control/border-box-control/component.js +2 -0
- package/build/border-box-control/border-box-control/component.js.map +1 -1
- package/build/border-box-control/border-box-control/hook.js +4 -1
- package/build/border-box-control/border-box-control/hook.js.map +1 -1
- package/build/border-control/border-control/component.js +2 -0
- package/build/border-control/border-control/component.js.map +1 -1
- package/build/disabled/index.js +6 -26
- package/build/disabled/index.js.map +1 -1
- package/build/font-size-picker/index.js +1 -1
- package/build/font-size-picker/index.js.map +1 -1
- package/build/font-size-picker/styles.js +5 -13
- package/build/font-size-picker/styles.js.map +1 -1
- package/build/font-size-picker/utils.js +1 -1
- package/build/font-size-picker/utils.js.map +1 -1
- package/build/form-token-field/suggestions-list.js +5 -5
- package/build/form-token-field/suggestions-list.js.map +1 -1
- package/build/higher-order/with-fallback-styles/index.js +1 -1
- package/build/higher-order/with-fallback-styles/index.js.map +1 -1
- package/build/index.js +8 -6
- package/build/index.js.map +1 -1
- package/build/modal/aria-helper.js +2 -3
- package/build/modal/aria-helper.js.map +1 -1
- package/build/modal/index.js +42 -11
- package/build/modal/index.js.map +1 -1
- package/build/modal/types.js +6 -0
- package/build/modal/types.js.map +1 -0
- package/build/navigator/index.js +8 -8
- package/build/navigator/index.js.map +1 -1
- package/build/navigator/navigator-back-button/component.js +5 -4
- package/build/navigator/navigator-back-button/component.js.map +1 -1
- package/build/navigator/navigator-back-button/index.js +1 -1
- package/build/navigator/navigator-back-button/index.js.map +1 -1
- package/build/navigator/navigator-button/component.js +5 -4
- package/build/navigator/navigator-button/component.js.map +1 -1
- package/build/navigator/navigator-button/index.js +1 -1
- package/build/navigator/navigator-button/index.js.map +1 -1
- package/build/navigator/navigator-provider/component.js +10 -7
- package/build/navigator/navigator-provider/component.js.map +1 -1
- package/build/navigator/navigator-provider/index.js +1 -1
- package/build/navigator/navigator-provider/index.js.map +1 -1
- package/build/navigator/navigator-screen/component.js +24 -27
- package/build/navigator/navigator-screen/component.js.map +1 -1
- package/build/navigator/navigator-screen/index.js +1 -1
- package/build/navigator/navigator-screen/index.js.map +1 -1
- package/build/sandbox/index.js +55 -59
- package/build/sandbox/index.js.map +1 -1
- package/build/sandbox/index.native.js +63 -62
- package/build/sandbox/index.native.js.map +1 -1
- package/build/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build/tab-panel/index.js +4 -4
- package/build/tab-panel/index.js.map +1 -1
- package/build/theme/index.js +62 -0
- package/build/theme/index.js.map +1 -0
- package/build/theme/styles.js +33 -0
- package/build/theme/styles.js.map +1 -0
- package/build/theme/types.js +6 -0
- package/build/theme/types.js.map +1 -0
- package/build/tools-panel/tools-panel/hook.js +3 -3
- package/build/tools-panel/tools-panel/hook.js.map +1 -1
- package/build/tools-panel/tools-panel-item/hook.js +6 -6
- package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
- package/build/tooltip/index.js +4 -1
- package/build/tooltip/index.js.map +1 -1
- package/build/tooltip/index.native.js +17 -4
- package/build/tooltip/index.native.js.map +1 -1
- package/build-module/border-box-control/border-box-control/component.js +2 -0
- package/build-module/border-box-control/border-box-control/component.js.map +1 -1
- package/build-module/border-box-control/border-box-control/hook.js +4 -1
- package/build-module/border-box-control/border-box-control/hook.js.map +1 -1
- package/build-module/border-control/border-control/component.js +2 -0
- package/build-module/border-control/border-control/component.js.map +1 -1
- package/build-module/disabled/index.js +7 -26
- package/build-module/disabled/index.js.map +1 -1
- package/build-module/font-size-picker/index.js +1 -1
- package/build-module/font-size-picker/index.js.map +1 -1
- package/build-module/font-size-picker/styles.js +5 -13
- package/build-module/font-size-picker/styles.js.map +1 -1
- package/build-module/font-size-picker/utils.js +1 -1
- package/build-module/font-size-picker/utils.js.map +1 -1
- package/build-module/form-token-field/suggestions-list.js +5 -5
- package/build-module/form-token-field/suggestions-list.js.map +1 -1
- package/build-module/higher-order/with-fallback-styles/index.js +2 -2
- package/build-module/higher-order/with-fallback-styles/index.js.map +1 -1
- package/build-module/index.js +2 -1
- package/build-module/index.js.map +1 -1
- package/build-module/modal/aria-helper.js +2 -3
- package/build-module/modal/aria-helper.js.map +1 -1
- package/build-module/modal/index.js +44 -12
- package/build-module/modal/index.js.map +1 -1
- package/build-module/modal/types.js +2 -0
- package/build-module/modal/types.js.map +1 -0
- package/build-module/navigator/index.js +4 -4
- package/build-module/navigator/index.js.map +1 -1
- package/build-module/navigator/navigator-back-button/component.js +3 -3
- package/build-module/navigator/navigator-back-button/component.js.map +1 -1
- package/build-module/navigator/navigator-back-button/index.js +1 -1
- package/build-module/navigator/navigator-back-button/index.js.map +1 -1
- package/build-module/navigator/navigator-button/component.js +3 -3
- package/build-module/navigator/navigator-button/component.js.map +1 -1
- package/build-module/navigator/navigator-button/index.js +1 -1
- package/build-module/navigator/navigator-button/index.js.map +1 -1
- package/build-module/navigator/navigator-provider/component.js +8 -6
- package/build-module/navigator/navigator-provider/component.js.map +1 -1
- package/build-module/navigator/navigator-provider/index.js +1 -1
- package/build-module/navigator/navigator-provider/index.js.map +1 -1
- package/build-module/navigator/navigator-screen/component.js +12 -26
- package/build-module/navigator/navigator-screen/component.js.map +1 -1
- package/build-module/navigator/navigator-screen/index.js +1 -1
- package/build-module/navigator/navigator-screen/index.js.map +1 -1
- package/build-module/sandbox/index.js +56 -59
- package/build-module/sandbox/index.js.map +1 -1
- package/build-module/sandbox/index.native.js +54 -52
- package/build-module/sandbox/index.native.js.map +1 -1
- package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build-module/tab-panel/index.js +4 -4
- package/build-module/tab-panel/index.js.map +1 -1
- package/build-module/theme/index.js +52 -0
- package/build-module/theme/index.js.map +1 -0
- package/build-module/theme/styles.js +25 -0
- package/build-module/theme/styles.js.map +1 -0
- package/build-module/theme/types.js +2 -0
- package/build-module/theme/types.js.map +1 -0
- package/build-module/tools-panel/tools-panel/hook.js +3 -3
- package/build-module/tools-panel/tools-panel/hook.js.map +1 -1
- package/build-module/tools-panel/tools-panel-item/hook.js +6 -6
- package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
- package/build-module/tooltip/index.js +4 -1
- package/build-module/tooltip/index.js.map +1 -1
- package/build-module/tooltip/index.native.js +17 -4
- package/build-module/tooltip/index.native.js.map +1 -1
- package/build-style/style-rtl.css +26 -22
- package/build-style/style.css +26 -22
- package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
- package/build-types/border-box-control/border-box-control/hook.d.ts +1 -0
- package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
- package/build-types/border-control/border-control/component.d.ts +1 -0
- package/build-types/border-control/border-control/component.d.ts.map +1 -1
- package/build-types/border-control/border-control/hook.d.ts +1 -0
- package/build-types/border-control/border-control/hook.d.ts.map +1 -1
- package/build-types/border-control/stories/index.d.ts +6 -0
- package/build-types/border-control/stories/index.d.ts.map +1 -1
- package/build-types/border-control/types.d.ts +4 -0
- package/build-types/border-control/types.d.ts.map +1 -1
- package/build-types/confirm-dialog/types.d.ts +5 -1
- package/build-types/confirm-dialog/types.d.ts.map +1 -1
- package/build-types/disabled/index.d.ts.map +1 -1
- package/build-types/font-size-picker/styles.d.ts.map +1 -1
- package/build-types/modal/aria-helper.d.ts +4 -4
- package/build-types/modal/aria-helper.d.ts.map +1 -1
- package/build-types/modal/index.d.ts +35 -2
- package/build-types/modal/index.d.ts.map +1 -1
- package/build-types/modal/stories/index.d.ts +9 -0
- package/build-types/modal/stories/index.d.ts.map +1 -0
- package/build-types/modal/test/aria-helper.d.ts +2 -0
- package/build-types/modal/test/aria-helper.d.ts.map +1 -0
- package/build-types/modal/test/index.d.ts +2 -0
- package/build-types/modal/test/index.d.ts.map +1 -0
- package/build-types/modal/types.d.ts +134 -0
- package/build-types/modal/types.d.ts.map +1 -0
- package/build-types/navigator/index.d.ts +4 -4
- package/build-types/navigator/index.d.ts.map +1 -1
- package/build-types/navigator/navigator-back-button/component.d.ts +4 -2
- package/build-types/navigator/navigator-back-button/component.d.ts.map +1 -1
- package/build-types/navigator/navigator-back-button/hook.d.ts +1 -0
- package/build-types/navigator/navigator-back-button/hook.d.ts.map +1 -1
- package/build-types/navigator/navigator-back-button/index.d.ts +1 -1
- package/build-types/navigator/navigator-back-button/index.d.ts.map +1 -1
- package/build-types/navigator/navigator-button/component.d.ts +4 -2
- package/build-types/navigator/navigator-button/component.d.ts.map +1 -1
- package/build-types/navigator/navigator-button/hook.d.ts +1 -0
- package/build-types/navigator/navigator-button/hook.d.ts.map +1 -1
- package/build-types/navigator/navigator-button/index.d.ts +1 -1
- package/build-types/navigator/navigator-button/index.d.ts.map +1 -1
- package/build-types/navigator/navigator-provider/component.d.ts +2 -2
- package/build-types/navigator/navigator-provider/component.d.ts.map +1 -1
- package/build-types/navigator/navigator-provider/index.d.ts +1 -1
- package/build-types/navigator/navigator-provider/index.d.ts.map +1 -1
- package/build-types/navigator/navigator-screen/component.d.ts +2 -2
- package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
- package/build-types/navigator/navigator-screen/index.d.ts +1 -1
- package/build-types/navigator/navigator-screen/index.d.ts.map +1 -1
- package/build-types/navigator/stories/index.d.ts +9 -0
- package/build-types/navigator/stories/index.d.ts.map +1 -0
- package/build-types/navigator/test/index.d.ts +2 -0
- package/build-types/navigator/test/index.d.ts.map +1 -0
- package/build-types/navigator/types.d.ts +4 -1
- package/build-types/navigator/types.d.ts.map +1 -1
- package/build-types/slot-fill/bubbles-virtually/slot-fill-provider.d.ts.map +1 -1
- package/build-types/tab-panel/index.d.ts.map +1 -1
- package/build-types/theme/index.d.ts +31 -0
- package/build-types/theme/index.d.ts.map +1 -0
- package/build-types/theme/stories/index.d.ts +13 -0
- package/build-types/theme/stories/index.d.ts.map +1 -0
- package/build-types/theme/styles.d.ts +10 -0
- package/build-types/theme/styles.d.ts.map +1 -0
- package/build-types/theme/test/index.d.ts +2 -0
- package/build-types/theme/test/index.d.ts.map +1 -0
- package/build-types/theme/types.d.ts +21 -0
- package/build-types/theme/types.d.ts.map +1 -0
- package/build-types/tools-panel/tools-panel/hook.d.ts.map +1 -1
- package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
- package/build-types/tooltip/index.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/base-field/test/index.js +4 -6
- package/src/border-box-control/border-box-control/component.tsx +2 -0
- package/src/border-box-control/border-box-control/hook.ts +4 -0
- package/src/border-box-control/test/index.js +7 -2
- package/src/border-control/border-control/README.md +6 -0
- package/src/border-control/border-control/component.tsx +2 -0
- package/src/border-control/types.ts +4 -0
- package/src/button/style.scss +25 -25
- package/src/button/test/index.js +3 -5
- package/src/combobox-control/test/index.js +1 -1
- package/src/confirm-dialog/types.ts +6 -0
- package/src/date-time/time/test/index.tsx +2 -6
- package/src/disabled/index.tsx +11 -33
- package/src/disabled/test/index.tsx +14 -82
- package/src/dropdown/test/index.js +4 -3
- package/src/font-size-picker/index.tsx +1 -1
- package/src/font-size-picker/styles.ts +3 -1
- package/src/font-size-picker/test/index.tsx +2 -2
- package/src/font-size-picker/test/utils.ts +5 -5
- package/src/font-size-picker/utils.ts +1 -1
- package/src/form-file-upload/test/index.tsx +1 -1
- package/src/form-token-field/suggestions-list.tsx +5 -5
- package/src/higher-order/with-fallback-styles/index.js +6 -2
- package/src/higher-order/with-focus-outside/test/index.js +44 -45
- package/src/higher-order/with-focus-return/test/index.js +34 -30
- package/src/higher-order/with-notices/test/index.js +1 -1
- package/src/index.js +2 -1
- package/src/input-control/test/index.js +2 -2
- package/src/item-group/test/index.js +2 -2
- package/src/menu-item/test/index.js +0 -3
- package/src/mobile/bottom-sheet/test/range-cell.native.js +16 -14
- package/src/modal/README.md +53 -54
- package/src/modal/{aria-helper.js → aria-helper.ts} +5 -7
- package/src/modal/{index.js → index.tsx} +48 -12
- package/src/modal/stories/{index.js → index.tsx} +47 -42
- package/src/modal/test/{aria-helper.js → aria-helper.ts} +0 -0
- package/src/modal/test/{index.js → index.tsx} +13 -3
- package/src/modal/types.ts +144 -0
- package/src/navigation/test/index.js +1 -1
- package/src/navigator/index.ts +4 -4
- package/src/navigator/navigator-back-button/component.tsx +4 -4
- package/src/navigator/navigator-back-button/index.ts +1 -1
- package/src/navigator/navigator-button/component.tsx +4 -4
- package/src/navigator/navigator-button/index.ts +1 -1
- package/src/navigator/navigator-provider/component.tsx +6 -4
- package/src/navigator/navigator-provider/index.ts +1 -1
- package/src/navigator/navigator-screen/component.tsx +20 -26
- package/src/navigator/navigator-screen/index.ts +1 -1
- package/src/navigator/stories/index.tsx +210 -0
- package/src/navigator/test/index.tsx +509 -0
- package/src/navigator/types.ts +2 -0
- package/src/notice/test/__snapshots__/index.js.snap +39 -38
- package/src/notice/test/index.js +15 -36
- package/src/notice/test/list.js +6 -14
- package/src/number-control/test/index.js +3 -2
- package/src/panel/test/body.js +2 -2
- package/src/placeholder/style.scss +5 -0
- package/src/sandbox/index.js +62 -47
- package/src/sandbox/index.native.js +72 -52
- package/src/sandbox/test/index.js +7 -10
- package/src/shortcut/test/index.tsx +1 -1
- package/src/slot-fill/bubbles-virtually/slot-fill-provider.js +5 -3
- package/src/style.scss +4 -0
- package/src/tab-panel/index.tsx +4 -7
- package/src/text-highlight/test/index.tsx +1 -3
- package/src/theme/README.md +34 -0
- package/src/theme/index.tsx +51 -0
- package/src/theme/stories/index.tsx +47 -0
- package/src/theme/styles.ts +28 -0
- package/src/theme/test/index.tsx +101 -0
- package/src/theme/types.ts +21 -0
- package/src/toolbar/test/index.js +2 -2
- package/src/toolbar-group/test/index.js +6 -10
- package/src/tools-panel/test/index.js +4 -6
- package/src/tools-panel/tools-panel/hook.ts +2 -9
- package/src/tools-panel/tools-panel-item/hook.ts +17 -3
- package/src/tooltip/index.js +3 -0
- package/src/tooltip/index.native.js +15 -0
- package/src/tooltip/test/index.native.js +1 -2
- package/src/tree-grid/test/__snapshots__/cell.js.snap +1 -3
- package/src/tree-grid/test/__snapshots__/roving-tab-index-item.js.snap +17 -15
- package/src/tree-grid/test/__snapshots__/row.js.snap +25 -21
- package/src/tree-grid/test/cell.js +4 -4
- package/src/tree-grid/test/roving-tab-index-item.js +8 -8
- package/src/tree-grid/test/roving-tab-index.js +3 -3
- package/src/tree-grid/test/row.js +20 -16
- package/src/truncate/test/index.tsx +4 -4
- package/src/ui/shortcut/test/index.js +2 -1
- package/src/ui/spinner/test/index.js +14 -13
- package/src/ui/tooltip/test/index.js +16 -14
- package/src/utils/theme-variables.scss +8 -0
- package/src/visually-hidden/README.md +4 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/src/navigator/stories/index.js +0 -194
- package/src/navigator/test/index.js +0 -472
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ReactNode, ForwardedRef, ComponentPropsWithoutRef } from 'react';
|
|
5
|
+
import { render, screen } from '@testing-library/react';
|
|
6
|
+
import userEvent from '@testing-library/user-event';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WordPress dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { useState } from '@wordpress/element';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Internal dependencies
|
|
15
|
+
*/
|
|
16
|
+
import {
|
|
17
|
+
NavigatorProvider,
|
|
18
|
+
NavigatorScreen,
|
|
19
|
+
NavigatorButton,
|
|
20
|
+
NavigatorBackButton,
|
|
21
|
+
} from '..';
|
|
22
|
+
|
|
23
|
+
jest.mock( 'framer-motion', () => {
|
|
24
|
+
const actual = jest.requireActual( 'framer-motion' );
|
|
25
|
+
return {
|
|
26
|
+
__esModule: true,
|
|
27
|
+
...actual,
|
|
28
|
+
AnimatePresence:
|
|
29
|
+
( { children }: { children?: ReactNode } ) =>
|
|
30
|
+
() =>
|
|
31
|
+
<div>{ children }</div>,
|
|
32
|
+
motion: {
|
|
33
|
+
...actual.motion,
|
|
34
|
+
div: require( 'react' ).forwardRef(
|
|
35
|
+
(
|
|
36
|
+
{ children }: { children?: ReactNode },
|
|
37
|
+
ref: ForwardedRef< HTMLDivElement >
|
|
38
|
+
) => <div ref={ ref }>{ children }</div>
|
|
39
|
+
),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
} );
|
|
43
|
+
|
|
44
|
+
const INVALID_HTML_ATTRIBUTE = {
|
|
45
|
+
raw: ' "\'><=invalid_path',
|
|
46
|
+
escaped: " "'><=invalid_path",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const PATHS = {
|
|
50
|
+
HOME: '/',
|
|
51
|
+
CHILD: '/child',
|
|
52
|
+
NESTED: '/child/nested',
|
|
53
|
+
INVALID_HTML_ATTRIBUTE: INVALID_HTML_ATTRIBUTE.raw,
|
|
54
|
+
NOT_FOUND: '/not-found',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const SCREEN_TEXT = {
|
|
58
|
+
home: 'This is the home screen.',
|
|
59
|
+
child: 'This is the child screen.',
|
|
60
|
+
nested: 'This is the nested screen.',
|
|
61
|
+
invalidHtmlPath: 'This is the screen with an invalid HTML value as a path.',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const BUTTON_TEXT = {
|
|
65
|
+
toNonExistingScreen: 'Navigate to non-existing screen.',
|
|
66
|
+
toChildScreen: 'Navigate to child screen.',
|
|
67
|
+
toNestedScreen: 'Navigate to nested screen.',
|
|
68
|
+
toInvalidHtmlPathScreen:
|
|
69
|
+
'Navigate to screen with an invalid HTML value as a path.',
|
|
70
|
+
back: 'Go back',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
type CustomTestOnClickHandler = (
|
|
74
|
+
args:
|
|
75
|
+
| {
|
|
76
|
+
type: 'goTo';
|
|
77
|
+
path: string;
|
|
78
|
+
}
|
|
79
|
+
| { type: 'goBack' }
|
|
80
|
+
) => void;
|
|
81
|
+
|
|
82
|
+
function CustomNavigatorButton( {
|
|
83
|
+
path,
|
|
84
|
+
onClick,
|
|
85
|
+
...props
|
|
86
|
+
}: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & {
|
|
87
|
+
onClick?: CustomTestOnClickHandler;
|
|
88
|
+
} ) {
|
|
89
|
+
return (
|
|
90
|
+
<NavigatorButton
|
|
91
|
+
onClick={ () => {
|
|
92
|
+
// Used to spy on the values passed to `navigator.goTo`.
|
|
93
|
+
onClick?.( { type: 'goTo', path } );
|
|
94
|
+
} }
|
|
95
|
+
path={ path }
|
|
96
|
+
{ ...props }
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function CustomNavigatorButtonWithFocusRestoration( {
|
|
102
|
+
path,
|
|
103
|
+
onClick,
|
|
104
|
+
...props
|
|
105
|
+
}: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & {
|
|
106
|
+
onClick?: CustomTestOnClickHandler;
|
|
107
|
+
} ) {
|
|
108
|
+
return (
|
|
109
|
+
<NavigatorButton
|
|
110
|
+
onClick={ () => {
|
|
111
|
+
// Used to spy on the values passed to `navigator.goTo`.
|
|
112
|
+
onClick?.( { type: 'goTo', path } );
|
|
113
|
+
} }
|
|
114
|
+
path={ path }
|
|
115
|
+
{ ...props }
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function CustomNavigatorBackButton( {
|
|
121
|
+
onClick,
|
|
122
|
+
...props
|
|
123
|
+
}: Omit< ComponentPropsWithoutRef< typeof NavigatorBackButton >, 'onClick' > & {
|
|
124
|
+
onClick?: CustomTestOnClickHandler;
|
|
125
|
+
} ) {
|
|
126
|
+
return (
|
|
127
|
+
<NavigatorBackButton
|
|
128
|
+
onClick={ () => {
|
|
129
|
+
// Used to spy on the values passed to `navigator.goBack`.
|
|
130
|
+
onClick?.( { type: 'goBack' } );
|
|
131
|
+
} }
|
|
132
|
+
{ ...props }
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const MyNavigation = ( {
|
|
138
|
+
initialPath = PATHS.HOME,
|
|
139
|
+
onNavigatorButtonClick,
|
|
140
|
+
}: {
|
|
141
|
+
initialPath?: string;
|
|
142
|
+
onNavigatorButtonClick?: CustomTestOnClickHandler;
|
|
143
|
+
} ) => {
|
|
144
|
+
const [ innerInputValue, setInnerInputValue ] = useState( '' );
|
|
145
|
+
const [ outerInputValue, setOuterInputValue ] = useState( '' );
|
|
146
|
+
return (
|
|
147
|
+
<>
|
|
148
|
+
<NavigatorProvider initialPath={ initialPath }>
|
|
149
|
+
<NavigatorScreen path={ PATHS.HOME }>
|
|
150
|
+
<p>{ SCREEN_TEXT.home }</p>
|
|
151
|
+
<CustomNavigatorButton
|
|
152
|
+
path={ PATHS.NOT_FOUND }
|
|
153
|
+
onClick={ onNavigatorButtonClick }
|
|
154
|
+
>
|
|
155
|
+
{ BUTTON_TEXT.toNonExistingScreen }
|
|
156
|
+
</CustomNavigatorButton>
|
|
157
|
+
<CustomNavigatorButton
|
|
158
|
+
path={ PATHS.CHILD }
|
|
159
|
+
onClick={ onNavigatorButtonClick }
|
|
160
|
+
>
|
|
161
|
+
{ BUTTON_TEXT.toChildScreen }
|
|
162
|
+
</CustomNavigatorButton>
|
|
163
|
+
<CustomNavigatorButton
|
|
164
|
+
path={ PATHS.INVALID_HTML_ATTRIBUTE }
|
|
165
|
+
onClick={ onNavigatorButtonClick }
|
|
166
|
+
>
|
|
167
|
+
{ BUTTON_TEXT.toInvalidHtmlPathScreen }
|
|
168
|
+
</CustomNavigatorButton>
|
|
169
|
+
</NavigatorScreen>
|
|
170
|
+
|
|
171
|
+
<NavigatorScreen path={ PATHS.CHILD }>
|
|
172
|
+
<p>{ SCREEN_TEXT.child }</p>
|
|
173
|
+
<CustomNavigatorButtonWithFocusRestoration
|
|
174
|
+
path={ PATHS.NESTED }
|
|
175
|
+
onClick={ onNavigatorButtonClick }
|
|
176
|
+
>
|
|
177
|
+
{ BUTTON_TEXT.toNestedScreen }
|
|
178
|
+
</CustomNavigatorButtonWithFocusRestoration>
|
|
179
|
+
<CustomNavigatorBackButton
|
|
180
|
+
onClick={ onNavigatorButtonClick }
|
|
181
|
+
>
|
|
182
|
+
{ BUTTON_TEXT.back }
|
|
183
|
+
</CustomNavigatorBackButton>
|
|
184
|
+
|
|
185
|
+
<label htmlFor="test-input-inner">Inner input</label>
|
|
186
|
+
<input
|
|
187
|
+
name="test-input-inner"
|
|
188
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
189
|
+
id="test-input-inner"
|
|
190
|
+
onChange={ ( e ) => {
|
|
191
|
+
setInnerInputValue( e.target.value );
|
|
192
|
+
} }
|
|
193
|
+
value={ innerInputValue }
|
|
194
|
+
/>
|
|
195
|
+
</NavigatorScreen>
|
|
196
|
+
|
|
197
|
+
<NavigatorScreen path={ PATHS.NESTED }>
|
|
198
|
+
<p>{ SCREEN_TEXT.nested }</p>
|
|
199
|
+
<CustomNavigatorBackButton
|
|
200
|
+
onClick={ onNavigatorButtonClick }
|
|
201
|
+
>
|
|
202
|
+
{ BUTTON_TEXT.back }
|
|
203
|
+
</CustomNavigatorBackButton>
|
|
204
|
+
</NavigatorScreen>
|
|
205
|
+
|
|
206
|
+
<NavigatorScreen path={ PATHS.INVALID_HTML_ATTRIBUTE }>
|
|
207
|
+
<p>{ SCREEN_TEXT.invalidHtmlPath }</p>
|
|
208
|
+
<CustomNavigatorBackButton
|
|
209
|
+
onClick={ onNavigatorButtonClick }
|
|
210
|
+
>
|
|
211
|
+
{ BUTTON_TEXT.back }
|
|
212
|
+
</CustomNavigatorBackButton>
|
|
213
|
+
</NavigatorScreen>
|
|
214
|
+
|
|
215
|
+
{ /* A `NavigatorScreen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ }
|
|
216
|
+
</NavigatorProvider>
|
|
217
|
+
|
|
218
|
+
<label htmlFor="test-input-outer">Outer input</label>
|
|
219
|
+
<input
|
|
220
|
+
name="test-input-outer"
|
|
221
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
222
|
+
id="test-input-outer"
|
|
223
|
+
onChange={ ( e ) => {
|
|
224
|
+
setOuterInputValue( e.target.value );
|
|
225
|
+
} }
|
|
226
|
+
value={ outerInputValue }
|
|
227
|
+
/>
|
|
228
|
+
</>
|
|
229
|
+
);
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const getScreen = ( screenKey: keyof typeof SCREEN_TEXT ) =>
|
|
233
|
+
screen.getByText( SCREEN_TEXT[ screenKey ] );
|
|
234
|
+
const queryScreen = ( screenKey: keyof typeof SCREEN_TEXT ) =>
|
|
235
|
+
screen.queryByText( SCREEN_TEXT[ screenKey ] );
|
|
236
|
+
const getNavigationButton = ( buttonKey: keyof typeof BUTTON_TEXT ) =>
|
|
237
|
+
screen.getByRole( 'button', { name: BUTTON_TEXT[ buttonKey ] } );
|
|
238
|
+
|
|
239
|
+
describe( 'Navigator', () => {
|
|
240
|
+
const originalGetClientRects = window.Element.prototype.getClientRects;
|
|
241
|
+
|
|
242
|
+
// `getClientRects` needs to be mocked so that `isVisible` from the `@wordpress/dom`
|
|
243
|
+
// `focusable` module can pass, in a JSDOM env where the DOM elements have no width/height.
|
|
244
|
+
const mockedGetClientRects = jest.fn( () => [
|
|
245
|
+
{
|
|
246
|
+
x: 0,
|
|
247
|
+
y: 0,
|
|
248
|
+
width: 100,
|
|
249
|
+
height: 100,
|
|
250
|
+
},
|
|
251
|
+
] );
|
|
252
|
+
|
|
253
|
+
beforeAll( () => {
|
|
254
|
+
// @ts-expect-error There's no need for an exact mock, this is just needed
|
|
255
|
+
// for the tests to pass (see `mockedGetClientRects` inline comments).
|
|
256
|
+
window.Element.prototype.getClientRects =
|
|
257
|
+
jest.fn( mockedGetClientRects );
|
|
258
|
+
} );
|
|
259
|
+
|
|
260
|
+
afterAll( () => {
|
|
261
|
+
window.Element.prototype.getClientRects = originalGetClientRects;
|
|
262
|
+
} );
|
|
263
|
+
|
|
264
|
+
it( 'should render', () => {
|
|
265
|
+
render( <MyNavigation /> );
|
|
266
|
+
|
|
267
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
268
|
+
expect( queryScreen( 'child' ) ).not.toBeInTheDocument();
|
|
269
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
270
|
+
} );
|
|
271
|
+
|
|
272
|
+
it( 'should show a different screen on the first render depending on the value of `initialPath`', () => {
|
|
273
|
+
render( <MyNavigation initialPath={ PATHS.CHILD } /> );
|
|
274
|
+
|
|
275
|
+
expect( queryScreen( 'home' ) ).not.toBeInTheDocument();
|
|
276
|
+
expect( getScreen( 'child' ) ).toBeInTheDocument();
|
|
277
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
278
|
+
} );
|
|
279
|
+
|
|
280
|
+
it( 'should ignore changes to `initialPath` after the first render', () => {
|
|
281
|
+
const { rerender } = render( <MyNavigation /> );
|
|
282
|
+
|
|
283
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
284
|
+
expect( queryScreen( 'child' ) ).not.toBeInTheDocument();
|
|
285
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
286
|
+
|
|
287
|
+
rerender( <MyNavigation initialPath={ PATHS.CHILD } /> );
|
|
288
|
+
|
|
289
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
290
|
+
expect( queryScreen( 'child' ) ).not.toBeInTheDocument();
|
|
291
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
292
|
+
} );
|
|
293
|
+
|
|
294
|
+
it( 'should not rended anything if the `initialPath` does not match any available screen', () => {
|
|
295
|
+
render( <MyNavigation initialPath={ PATHS.NOT_FOUND } /> );
|
|
296
|
+
|
|
297
|
+
expect( queryScreen( 'home' ) ).not.toBeInTheDocument();
|
|
298
|
+
expect( queryScreen( 'child' ) ).not.toBeInTheDocument();
|
|
299
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
300
|
+
} );
|
|
301
|
+
|
|
302
|
+
it( 'should navigate across screens', async () => {
|
|
303
|
+
const spy = jest.fn();
|
|
304
|
+
|
|
305
|
+
const user = userEvent.setup( {
|
|
306
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
307
|
+
} );
|
|
308
|
+
|
|
309
|
+
render( <MyNavigation onNavigatorButtonClick={ spy } /> );
|
|
310
|
+
|
|
311
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
312
|
+
expect( getNavigationButton( 'toChildScreen' ) ).toBeInTheDocument();
|
|
313
|
+
|
|
314
|
+
// Navigate to child screen.
|
|
315
|
+
await user.click( getNavigationButton( 'toChildScreen' ) );
|
|
316
|
+
|
|
317
|
+
expect( getScreen( 'child' ) ).toBeInTheDocument();
|
|
318
|
+
expect( getNavigationButton( 'back' ) ).toBeInTheDocument();
|
|
319
|
+
|
|
320
|
+
// Navigate back to home screen.
|
|
321
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
322
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
323
|
+
expect( getNavigationButton( 'toChildScreen' ) ).toBeInTheDocument();
|
|
324
|
+
|
|
325
|
+
// Navigate again to child screen.
|
|
326
|
+
await user.click( getNavigationButton( 'toChildScreen' ) );
|
|
327
|
+
|
|
328
|
+
expect( getScreen( 'child' ) ).toBeInTheDocument();
|
|
329
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toBeInTheDocument();
|
|
330
|
+
|
|
331
|
+
// Navigate to nested screen.
|
|
332
|
+
await user.click( getNavigationButton( 'toNestedScreen' ) );
|
|
333
|
+
|
|
334
|
+
expect( getScreen( 'nested' ) ).toBeInTheDocument();
|
|
335
|
+
expect( getNavigationButton( 'back' ) ).toBeInTheDocument();
|
|
336
|
+
|
|
337
|
+
// Navigate back to child screen.
|
|
338
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
339
|
+
|
|
340
|
+
expect( getScreen( 'child' ) ).toBeInTheDocument();
|
|
341
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toBeInTheDocument();
|
|
342
|
+
|
|
343
|
+
// Navigate back to home screen.
|
|
344
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
345
|
+
|
|
346
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
347
|
+
expect( getNavigationButton( 'toChildScreen' ) ).toBeInTheDocument();
|
|
348
|
+
|
|
349
|
+
// Check the values passed to `navigator.goTo()`.
|
|
350
|
+
expect( spy ).toHaveBeenCalledTimes( 6 );
|
|
351
|
+
expect( spy ).toHaveBeenNthCalledWith( 1, {
|
|
352
|
+
path: PATHS.CHILD,
|
|
353
|
+
type: 'goTo',
|
|
354
|
+
} );
|
|
355
|
+
expect( spy ).toHaveBeenNthCalledWith( 2, {
|
|
356
|
+
type: 'goBack',
|
|
357
|
+
} );
|
|
358
|
+
expect( spy ).toHaveBeenNthCalledWith( 3, {
|
|
359
|
+
path: PATHS.CHILD,
|
|
360
|
+
type: 'goTo',
|
|
361
|
+
} );
|
|
362
|
+
expect( spy ).toHaveBeenNthCalledWith( 4, {
|
|
363
|
+
path: PATHS.NESTED,
|
|
364
|
+
type: 'goTo',
|
|
365
|
+
} );
|
|
366
|
+
expect( spy ).toHaveBeenNthCalledWith( 5, {
|
|
367
|
+
type: 'goBack',
|
|
368
|
+
} );
|
|
369
|
+
expect( spy ).toHaveBeenNthCalledWith( 6, {
|
|
370
|
+
type: 'goBack',
|
|
371
|
+
} );
|
|
372
|
+
} );
|
|
373
|
+
|
|
374
|
+
it( 'should not rended anything if the path does not match any available screen', async () => {
|
|
375
|
+
const spy = jest.fn();
|
|
376
|
+
|
|
377
|
+
const user = userEvent.setup( {
|
|
378
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
379
|
+
} );
|
|
380
|
+
|
|
381
|
+
render( <MyNavigation onNavigatorButtonClick={ spy } /> );
|
|
382
|
+
|
|
383
|
+
expect(
|
|
384
|
+
getNavigationButton( 'toNonExistingScreen' )
|
|
385
|
+
).toBeInTheDocument();
|
|
386
|
+
|
|
387
|
+
// Attempt to navigate to non-existing screen. No screens get rendered.
|
|
388
|
+
await user.click( getNavigationButton( 'toNonExistingScreen' ) );
|
|
389
|
+
|
|
390
|
+
expect( queryScreen( 'home' ) ).not.toBeInTheDocument();
|
|
391
|
+
expect( queryScreen( 'child' ) ).not.toBeInTheDocument();
|
|
392
|
+
expect( queryScreen( 'nested' ) ).not.toBeInTheDocument();
|
|
393
|
+
|
|
394
|
+
// Check the values passed to `navigator.goTo()`.
|
|
395
|
+
expect( spy ).toHaveBeenCalledTimes( 1 );
|
|
396
|
+
expect( spy ).toHaveBeenNthCalledWith( 1, {
|
|
397
|
+
path: PATHS.NOT_FOUND,
|
|
398
|
+
type: 'goTo',
|
|
399
|
+
} );
|
|
400
|
+
} );
|
|
401
|
+
|
|
402
|
+
it( 'should escape the value of the `path` prop', async () => {
|
|
403
|
+
const user = userEvent.setup( {
|
|
404
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
405
|
+
} );
|
|
406
|
+
|
|
407
|
+
render( <MyNavigation /> );
|
|
408
|
+
|
|
409
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
410
|
+
expect(
|
|
411
|
+
getNavigationButton( 'toInvalidHtmlPathScreen' )
|
|
412
|
+
).toBeInTheDocument();
|
|
413
|
+
|
|
414
|
+
// The following line tests the implementation details, but it's necessary
|
|
415
|
+
// as this would be otherwise transparent to the user.
|
|
416
|
+
expect(
|
|
417
|
+
getNavigationButton( 'toInvalidHtmlPathScreen' )
|
|
418
|
+
).toHaveAttribute( 'id', INVALID_HTML_ATTRIBUTE.escaped );
|
|
419
|
+
|
|
420
|
+
// Navigate to screen with an invalid HTML value for its `path`.
|
|
421
|
+
await user.click( getNavigationButton( 'toInvalidHtmlPathScreen' ) );
|
|
422
|
+
|
|
423
|
+
expect( getScreen( 'invalidHtmlPath' ) ).toBeInTheDocument();
|
|
424
|
+
expect( getNavigationButton( 'back' ) ).toBeInTheDocument();
|
|
425
|
+
|
|
426
|
+
// Navigate back to home screen, check that the focus restoration selector
|
|
427
|
+
// worked correctly despite the escaping.
|
|
428
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
429
|
+
|
|
430
|
+
expect( getScreen( 'home' ) ).toBeInTheDocument();
|
|
431
|
+
expect(
|
|
432
|
+
getNavigationButton( 'toInvalidHtmlPathScreen' )
|
|
433
|
+
).toHaveFocus();
|
|
434
|
+
} );
|
|
435
|
+
|
|
436
|
+
describe( 'focus management', () => {
|
|
437
|
+
it( 'should restore focus correctly', async () => {
|
|
438
|
+
const user = userEvent.setup( {
|
|
439
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
440
|
+
} );
|
|
441
|
+
|
|
442
|
+
render( <MyNavigation /> );
|
|
443
|
+
|
|
444
|
+
// Navigate to child screen.
|
|
445
|
+
await user.click( getNavigationButton( 'toChildScreen' ) );
|
|
446
|
+
|
|
447
|
+
// The first tabbable element receives focus.
|
|
448
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toHaveFocus();
|
|
449
|
+
|
|
450
|
+
// Navigate to nested screen.
|
|
451
|
+
await user.click( getNavigationButton( 'toNestedScreen' ) );
|
|
452
|
+
|
|
453
|
+
// The first tabbable element receives focus.
|
|
454
|
+
expect( getNavigationButton( 'back' ) ).toHaveFocus();
|
|
455
|
+
|
|
456
|
+
// Navigate back to child screen.
|
|
457
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
458
|
+
|
|
459
|
+
// The first tabbable element receives focus.
|
|
460
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toHaveFocus();
|
|
461
|
+
|
|
462
|
+
// Navigate back to home screen, check that focus was correctly restored.
|
|
463
|
+
await user.click( getNavigationButton( 'back' ) );
|
|
464
|
+
|
|
465
|
+
// The first tabbable element receives focus.
|
|
466
|
+
expect( getNavigationButton( 'toChildScreen' ) ).toHaveFocus();
|
|
467
|
+
} );
|
|
468
|
+
|
|
469
|
+
it( 'should keep focus on an active element inside navigator, while re-rendering', async () => {
|
|
470
|
+
const user = userEvent.setup( {
|
|
471
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
472
|
+
} );
|
|
473
|
+
|
|
474
|
+
render( <MyNavigation /> );
|
|
475
|
+
|
|
476
|
+
// Navigate to child screen.
|
|
477
|
+
await user.click( getNavigationButton( 'toChildScreen' ) );
|
|
478
|
+
|
|
479
|
+
// The first tabbable element receives focus.
|
|
480
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toHaveFocus();
|
|
481
|
+
|
|
482
|
+
// Interact with the inner input.
|
|
483
|
+
// The focus should stay on the input element.
|
|
484
|
+
const innerInput = screen.getByLabelText( 'Inner input' );
|
|
485
|
+
await user.type( innerInput, 'd' );
|
|
486
|
+
expect( innerInput ).toHaveFocus();
|
|
487
|
+
} );
|
|
488
|
+
|
|
489
|
+
it( 'should keep focus on an active element outside navigator, while re-rendering', async () => {
|
|
490
|
+
const user = userEvent.setup( {
|
|
491
|
+
advanceTimers: jest.advanceTimersByTime,
|
|
492
|
+
} );
|
|
493
|
+
|
|
494
|
+
render( <MyNavigation /> );
|
|
495
|
+
|
|
496
|
+
// Navigate to child screen.
|
|
497
|
+
await user.click( getNavigationButton( 'toChildScreen' ) );
|
|
498
|
+
|
|
499
|
+
// The first tabbable element receives focus.
|
|
500
|
+
expect( getNavigationButton( 'toNestedScreen' ) ).toHaveFocus();
|
|
501
|
+
|
|
502
|
+
// Interact with the outer input.
|
|
503
|
+
// The focus should stay on the input element.
|
|
504
|
+
const outerInput = screen.getByLabelText( 'Outer input' );
|
|
505
|
+
await user.type( outerInput, 'd' );
|
|
506
|
+
expect( outerInput ).toHaveFocus();
|
|
507
|
+
} );
|
|
508
|
+
} );
|
|
509
|
+
} );
|
package/src/navigator/types.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type NavigatorLocation = NavigateOptions & {
|
|
|
11
11
|
isInitial?: boolean;
|
|
12
12
|
isBack?: boolean;
|
|
13
13
|
path?: string;
|
|
14
|
+
hasRestoredFocus?: boolean;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export type NavigatorContext = {
|
|
@@ -47,6 +48,7 @@ export type NavigatorScreenProps = {
|
|
|
47
48
|
type ButtonProps = {
|
|
48
49
|
// TODO: should also extend `Button` prop types once the `Button` component
|
|
49
50
|
// is refactored to TypeScript.
|
|
51
|
+
variant?: 'primary' | 'secondary' | 'tertiary' | 'link';
|
|
50
52
|
};
|
|
51
53
|
export type NavigatorBackButtonProps = Omit< ButtonProps, 'href' > & {
|
|
52
54
|
/**
|
|
@@ -1,54 +1,55 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`Notice should match snapshot 1`] = `
|
|
4
|
-
<div
|
|
5
|
-
className="components-notice is-success is-dismissible"
|
|
6
|
-
>
|
|
4
|
+
<div>
|
|
7
5
|
<div
|
|
8
|
-
|
|
6
|
+
class="components-notice is-success is-dismissible"
|
|
9
7
|
>
|
|
10
|
-
Example
|
|
11
8
|
<div
|
|
12
|
-
|
|
9
|
+
class="components-notice__content"
|
|
13
10
|
>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
variant="link"
|
|
11
|
+
Example
|
|
12
|
+
<div
|
|
13
|
+
class="components-notice__actions"
|
|
18
14
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
15
|
+
<a
|
|
16
|
+
class="components-button components-notice__action is-link"
|
|
17
|
+
href="https://example.com"
|
|
18
|
+
>
|
|
19
|
+
More information
|
|
20
|
+
</a>
|
|
21
|
+
<button
|
|
22
|
+
class="components-button components-notice__action is-secondary"
|
|
23
|
+
type="button"
|
|
24
|
+
>
|
|
25
|
+
Cancel
|
|
26
|
+
</button>
|
|
27
|
+
<button
|
|
28
|
+
class="components-button components-notice__action is-primary"
|
|
29
|
+
type="button"
|
|
30
|
+
>
|
|
31
|
+
Submit
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
35
34
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
<button
|
|
36
|
+
aria-label="Dismiss this notice"
|
|
37
|
+
class="components-button components-notice__dismiss has-icon"
|
|
38
|
+
type="button"
|
|
39
|
+
>
|
|
40
|
+
<svg
|
|
41
|
+
aria-hidden="true"
|
|
42
|
+
focusable="false"
|
|
43
|
+
height="24"
|
|
41
44
|
viewBox="0 0 24 24"
|
|
45
|
+
width="24"
|
|
42
46
|
xmlns="http://www.w3.org/2000/svg"
|
|
43
47
|
>
|
|
44
|
-
<
|
|
48
|
+
<path
|
|
45
49
|
d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"
|
|
46
50
|
/>
|
|
47
|
-
</
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
onClick={[Function]}
|
|
51
|
-
showTooltip={false}
|
|
52
|
-
/>
|
|
51
|
+
</svg>
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
53
54
|
</div>
|
|
54
55
|
`;
|