@patternfly/react-core 4.198.14 → 4.198.17
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 +24 -0
- package/dist/esm/components/Form/FormFieldGroup.d.ts +1 -1
- package/dist/esm/components/Form/FormFieldGroupExpandable.d.ts +2 -2
- package/dist/esm/components/Form/FormFieldGroupHeader.d.ts +3 -1
- package/dist/esm/components/Form/FormFieldGroupHeader.d.ts.map +1 -1
- package/dist/esm/components/Form/FormFieldGroupHeader.js.map +1 -1
- package/dist/esm/components/Form/InternalFormFieldGroup.d.ts +2 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadMain.d.ts +10 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadMain.d.ts.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadMain.js +9 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadMain.js.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadStatus.d.ts +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadStatus.d.ts.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadStatus.js +21 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadStatus.js.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadStatusItem.js.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitle.d.ts +6 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitle.d.ts.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitle.js +9 -2
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitle.js.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitleIcon.d.ts +2 -0
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitleIcon.d.ts.map +1 -1
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitleIcon.js +2 -4
- package/dist/esm/components/MultipleFileUpload/MultipleFileUploadTitleIcon.js.map +1 -1
- package/dist/esm/components/MultipleFileUpload/index.d.ts +0 -6
- package/dist/esm/components/MultipleFileUpload/index.d.ts.map +1 -1
- package/dist/esm/components/MultipleFileUpload/index.js +0 -6
- package/dist/esm/components/MultipleFileUpload/index.js.map +1 -1
- package/dist/esm/components/Tabs/Tab.d.ts +3 -1
- package/dist/esm/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/esm/components/Tabs/Tab.js +4 -3
- package/dist/esm/components/Tabs/Tab.js.map +1 -1
- package/dist/esm/components/Tabs/TabButton.d.ts +2 -0
- package/dist/esm/components/Tabs/TabButton.d.ts.map +1 -1
- package/dist/esm/components/Tabs/TabButton.js +2 -2
- package/dist/esm/components/Tabs/TabButton.js.map +1 -1
- package/dist/esm/components/Tile/Tile.d.ts.map +1 -1
- package/dist/esm/components/Tile/Tile.js +1 -1
- package/dist/esm/components/Tile/Tile.js.map +1 -1
- package/dist/js/components/Form/FormFieldGroup.d.ts +1 -1
- package/dist/js/components/Form/FormFieldGroupExpandable.d.ts +2 -2
- package/dist/js/components/Form/FormFieldGroupHeader.d.ts +3 -1
- package/dist/js/components/Form/FormFieldGroupHeader.d.ts.map +1 -1
- package/dist/js/components/Form/FormFieldGroupHeader.js.map +1 -1
- package/dist/js/components/Form/InternalFormFieldGroup.d.ts +2 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadMain.d.ts +10 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadMain.d.ts.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadMain.js +9 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadMain.js.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadStatus.d.ts +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadStatus.d.ts.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadStatus.js +21 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadStatus.js.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadStatusItem.js.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitle.d.ts +6 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitle.d.ts.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitle.js +9 -2
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitle.js.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitleIcon.d.ts +2 -0
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitleIcon.d.ts.map +1 -1
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitleIcon.js +2 -4
- package/dist/js/components/MultipleFileUpload/MultipleFileUploadTitleIcon.js.map +1 -1
- package/dist/js/components/MultipleFileUpload/index.d.ts +0 -6
- package/dist/js/components/MultipleFileUpload/index.d.ts.map +1 -1
- package/dist/js/components/MultipleFileUpload/index.js +0 -6
- package/dist/js/components/MultipleFileUpload/index.js.map +1 -1
- package/dist/js/components/Tabs/Tab.d.ts +3 -1
- package/dist/js/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/js/components/Tabs/Tab.js +4 -3
- package/dist/js/components/Tabs/Tab.js.map +1 -1
- package/dist/js/components/Tabs/TabButton.d.ts +2 -0
- package/dist/js/components/Tabs/TabButton.d.ts.map +1 -1
- package/dist/js/components/Tabs/TabButton.js +2 -2
- package/dist/js/components/Tabs/TabButton.js.map +1 -1
- package/dist/js/components/Tile/Tile.d.ts.map +1 -1
- package/dist/js/components/Tile/Tile.js +1 -1
- package/dist/js/components/Tile/Tile.js.map +1 -1
- package/dist/umd/react-core.css +10 -10
- package/dist/umd/react-core.js +65 -48
- package/dist/umd/react-core.min.css +10 -10
- package/dist/umd/react-core.min.js +4 -4
- package/package.json +5 -5
- package/src/components/Form/FormFieldGroup.tsx +1 -1
- package/src/components/Form/FormFieldGroupExpandable.tsx +2 -2
- package/src/components/Form/FormFieldGroupHeader.tsx +5 -1
- package/src/components/Form/InternalFormFieldGroup.tsx +2 -2
- package/src/components/Form/__tests__/FormFieldGroup.test.tsx +1 -1
- package/src/components/Form/__tests__/__snapshots__/FormFieldGroup.test.tsx.snap +1 -1
- package/src/components/Form/examples/Form.md +1 -1
- package/src/components/MultipleFileUpload/MultipleFileUploadMain.tsx +29 -8
- package/src/components/MultipleFileUpload/MultipleFileUploadStatus.tsx +24 -4
- package/src/components/MultipleFileUpload/MultipleFileUploadStatusItem.tsx +1 -1
- package/src/components/MultipleFileUpload/MultipleFileUploadTitle.tsx +19 -5
- package/src/components/MultipleFileUpload/MultipleFileUploadTitleIcon.tsx +4 -3
- package/src/components/MultipleFileUpload/__tests__/MultipleFileUploadMain.test.tsx +19 -2
- package/src/components/MultipleFileUpload/__tests__/MultipleFileUploadTitle.test.tsx +17 -2
- package/src/components/MultipleFileUpload/__tests__/MultipleFileUploadTitleIcon.test.tsx +1 -1
- package/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadMain.test.tsx.snap +198 -2
- package/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadTitle.test.tsx.snap +62 -4
- package/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadTitleIcon.test.tsx.snap +2 -50
- package/src/components/MultipleFileUpload/examples/MultipleFileUpload.md +7 -60
- package/src/components/MultipleFileUpload/examples/MultipleFileUploadBasic.tsx +48 -74
- package/src/components/MultipleFileUpload/index.ts +0 -6
- package/src/components/Tabs/Tab.tsx +31 -24
- package/src/components/Tabs/TabButton.tsx +5 -1
- package/src/components/Tabs/examples/Tabs.md +527 -256
- package/src/components/Tile/Tile.tsx +3 -0
- package/src/components/Tile/__tests__/__snapshots__/Tile.test.tsx.snap +9 -0
- package/src/components/Tile/examples/Tile.md +41 -39
- package/src/demos/ComposableMenu/ComposableMenu.md +4 -9
- package/src/demos/ComposableMenu/examples/ComposableDateSelect.tsx +113 -0
- package/src/demos/MultipleFileUploadDemos.md +16 -0
- package/src/demos/TileDemo.md +17 -35
- package/src/{components/MultipleFileUpload/examples/MultipleFileUploadHorizontal.tsx → demos/examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx} +60 -64
|
@@ -33,6 +33,9 @@ export const Tile: React.FunctionComponent<TileProps> = ({
|
|
|
33
33
|
...props
|
|
34
34
|
}: TileProps) => (
|
|
35
35
|
<div
|
|
36
|
+
role="option"
|
|
37
|
+
aria-selected={isSelected}
|
|
38
|
+
{...(isDisabled && { 'aria-disabled': isDisabled })}
|
|
36
39
|
className={css(
|
|
37
40
|
styles.tile,
|
|
38
41
|
isSelected && styles.modifiers.selected,
|
|
@@ -4,6 +4,7 @@ exports[`Tile basic 1`] = `
|
|
|
4
4
|
<div>
|
|
5
5
|
<div
|
|
6
6
|
class="pf-c-tile"
|
|
7
|
+
role="option"
|
|
7
8
|
tabindex="0"
|
|
8
9
|
>
|
|
9
10
|
<div
|
|
@@ -22,7 +23,9 @@ exports[`Tile basic 1`] = `
|
|
|
22
23
|
exports[`Tile renders disabled 1`] = `
|
|
23
24
|
<div>
|
|
24
25
|
<div
|
|
26
|
+
aria-disabled="true"
|
|
25
27
|
class="pf-c-tile pf-m-disabled"
|
|
28
|
+
role="option"
|
|
26
29
|
tabindex="0"
|
|
27
30
|
>
|
|
28
31
|
<div
|
|
@@ -41,7 +44,9 @@ exports[`Tile renders disabled 1`] = `
|
|
|
41
44
|
exports[`Tile renders selected 1`] = `
|
|
42
45
|
<div>
|
|
43
46
|
<div
|
|
47
|
+
aria-selected="true"
|
|
44
48
|
class="pf-c-tile pf-m-selected"
|
|
49
|
+
role="option"
|
|
45
50
|
tabindex="0"
|
|
46
51
|
>
|
|
47
52
|
<div
|
|
@@ -61,6 +66,7 @@ exports[`Tile renders with icon 1`] = `
|
|
|
61
66
|
<div>
|
|
62
67
|
<div
|
|
63
68
|
class="pf-c-tile"
|
|
69
|
+
role="option"
|
|
64
70
|
tabindex="0"
|
|
65
71
|
>
|
|
66
72
|
<div
|
|
@@ -97,6 +103,7 @@ exports[`Tile renders with stacked icon 1`] = `
|
|
|
97
103
|
<div>
|
|
98
104
|
<div
|
|
99
105
|
class="pf-c-tile"
|
|
106
|
+
role="option"
|
|
100
107
|
tabindex="0"
|
|
101
108
|
>
|
|
102
109
|
<div
|
|
@@ -133,6 +140,7 @@ exports[`Tile renders with stacked large icon 1`] = `
|
|
|
133
140
|
<div>
|
|
134
141
|
<div
|
|
135
142
|
class="pf-c-tile pf-m-display-lg"
|
|
143
|
+
role="option"
|
|
136
144
|
tabindex="0"
|
|
137
145
|
>
|
|
138
146
|
<div
|
|
@@ -169,6 +177,7 @@ exports[`Tile renders with subtext 1`] = `
|
|
|
169
177
|
<div>
|
|
170
178
|
<div
|
|
171
179
|
class="pf-c-tile"
|
|
180
|
+
role="option"
|
|
172
181
|
tabindex="0"
|
|
173
182
|
>
|
|
174
183
|
<div
|
|
@@ -9,7 +9,6 @@ beta: true
|
|
|
9
9
|
import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
|
|
10
10
|
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
## Examples
|
|
14
13
|
|
|
15
14
|
Keyboard interaction patterns and a11y is implemented in the Tile demos, located in the [Demo section](/documentation/react/demos/tiledemo).
|
|
@@ -20,29 +19,30 @@ Keyboard interaction patterns and a11y is implemented in the Tile demos, located
|
|
|
20
19
|
import React from 'react';
|
|
21
20
|
import { Tile } from '@patternfly/react-core';
|
|
22
21
|
|
|
23
|
-
<
|
|
24
|
-
<Tile title="Default" />
|
|
22
|
+
<div role="listbox" aria-label="Basic tiles">
|
|
23
|
+
<Tile title="Default" isSelected={false} />
|
|
25
24
|
<Tile title="Selected" isSelected />
|
|
26
|
-
<Tile title="Disabled" isDisabled />
|
|
27
|
-
</
|
|
25
|
+
<Tile title="Disabled" isDisabled isSelected={false} />
|
|
26
|
+
</div>;
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
|
|
31
29
|
### With subtext
|
|
32
30
|
|
|
33
31
|
```js
|
|
34
32
|
import React from 'react';
|
|
35
33
|
import { Tile } from '@patternfly/react-core';
|
|
36
34
|
|
|
37
|
-
<
|
|
38
|
-
<Tile title="Default"
|
|
35
|
+
<div role="listbox" aria-label="Tiles with subtext">
|
|
36
|
+
<Tile title="Default" isSelected={false}>
|
|
37
|
+
Subtext goes here
|
|
38
|
+
</Tile>{' '}
|
|
39
39
|
<Tile title="Selected" isSelected>
|
|
40
40
|
Subtext goes here
|
|
41
41
|
</Tile>{' '}
|
|
42
|
-
<Tile title="Disabled" isDisabled>
|
|
42
|
+
<Tile title="Disabled" isDisabled isSelected={false}>
|
|
43
43
|
Subtext goes here
|
|
44
44
|
</Tile>
|
|
45
|
-
</
|
|
45
|
+
</div>;
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
### With icon
|
|
@@ -52,17 +52,17 @@ import React from 'react';
|
|
|
52
52
|
import { Tile } from '@patternfly/react-core';
|
|
53
53
|
import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
|
|
54
54
|
|
|
55
|
-
<
|
|
56
|
-
<Tile title="Default" icon={<PlusIcon />}>
|
|
55
|
+
<div role="listbox" aria-label="Tiles with icon">
|
|
56
|
+
<Tile title="Default" icon={<PlusIcon />} isSelected={false}>
|
|
57
57
|
Subtext goes here
|
|
58
58
|
</Tile>{' '}
|
|
59
59
|
<Tile title="Selected" icon={<PlusIcon />} isSelected>
|
|
60
60
|
Subtext goes here
|
|
61
61
|
</Tile>{' '}
|
|
62
|
-
<Tile title="Disabled" icon={<PlusIcon />} isDisabled>
|
|
62
|
+
<Tile title="Disabled" icon={<PlusIcon />} isDisabled isSelected={false}>
|
|
63
63
|
Subtext goes here
|
|
64
64
|
</Tile>
|
|
65
|
-
</
|
|
65
|
+
</div>;
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
### Stacked
|
|
@@ -72,17 +72,17 @@ import React from 'react';
|
|
|
72
72
|
import { Tile } from '@patternfly/react-core';
|
|
73
73
|
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
|
|
74
74
|
|
|
75
|
-
<
|
|
76
|
-
<Tile title="Default" icon={<BellIcon />} isStacked>
|
|
75
|
+
<div role="listbox" aria-label="Stacked tiles">
|
|
76
|
+
<Tile title="Default" icon={<BellIcon />} isStacked isSelected={false}>
|
|
77
77
|
Subtext goes here
|
|
78
78
|
</Tile>{' '}
|
|
79
79
|
<Tile title="Selected" icon={<BellIcon />} isStacked isSelected>
|
|
80
80
|
Subtext goes here
|
|
81
81
|
</Tile>{' '}
|
|
82
|
-
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisabled>
|
|
82
|
+
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisabled isSelected={false}>
|
|
83
83
|
Subtext goes here
|
|
84
84
|
</Tile>
|
|
85
|
-
</
|
|
85
|
+
</div>;
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
### Stacked with large icons
|
|
@@ -92,17 +92,17 @@ import React from 'react';
|
|
|
92
92
|
import { Tile } from '@patternfly/react-core';
|
|
93
93
|
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
|
|
94
94
|
|
|
95
|
-
<
|
|
96
|
-
<Tile title="Default" icon={<BellIcon />} isStacked isDisplayLarge>
|
|
95
|
+
<div role="listbox" aria-label="Stacked tiles with large icons">
|
|
96
|
+
<Tile title="Default" icon={<BellIcon />} isStacked isDisplayLarge isSelected={false}>
|
|
97
97
|
Subtext goes here
|
|
98
98
|
</Tile>{' '}
|
|
99
99
|
<Tile title="Selected" icon={<BellIcon />} isStacked isDisplayLarge isSelected>
|
|
100
100
|
Subtext goes here
|
|
101
101
|
</Tile>{' '}
|
|
102
|
-
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisplayLarge isDisabled>
|
|
102
|
+
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisplayLarge isDisabled isSelected={false}>
|
|
103
103
|
Subtext goes here
|
|
104
104
|
</Tile>
|
|
105
|
-
</
|
|
105
|
+
</div>;
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
### With extra content
|
|
@@ -112,22 +112,24 @@ import React from 'react';
|
|
|
112
112
|
import { Tile, Flex } from '@patternfly/react-core';
|
|
113
113
|
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
|
|
114
114
|
|
|
115
|
-
<
|
|
116
|
-
<Flex
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
115
|
+
<div role="listbox" aria-label="Tiles with extra content">
|
|
116
|
+
<Flex>
|
|
117
|
+
<Flex flex={{ default: 'flex_1' }}>
|
|
118
|
+
<Tile title="Default" icon={<BellIcon />} isStacked isSelected={false}>
|
|
119
|
+
This is really really long subtext that goes on for so long that it has to wrap to the next line. This is really
|
|
120
|
+
really long subtext that goes on for so long that it has to wrap to the next line.
|
|
121
|
+
</Tile>
|
|
122
|
+
</Flex>
|
|
123
|
+
<Flex flex={{ default: 'flex_1' }}>
|
|
124
|
+
<Tile title="Selected" icon={<BellIcon />} isStacked isSelected>
|
|
125
|
+
This is really really long subtext that goes on for so long that it has to wrap to the next line.
|
|
126
|
+
</Tile>
|
|
127
|
+
</Flex>
|
|
128
|
+
<Flex flex={{ default: 'flex_1' }}>
|
|
129
|
+
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisabled isSelected={false}>
|
|
130
|
+
Subtext goes here
|
|
131
|
+
</Tile>
|
|
132
|
+
</Flex>
|
|
131
133
|
</Flex>
|
|
132
|
-
</
|
|
134
|
+
</div>;
|
|
133
135
|
```
|
|
@@ -28,31 +28,26 @@ Composable menus currently require consumer keyboard handling and use of our und
|
|
|
28
28
|
### Composable simple dropdown
|
|
29
29
|
|
|
30
30
|
```ts file="./examples/ComposableSimpleDropdown.tsx"
|
|
31
|
-
|
|
32
31
|
```
|
|
33
32
|
|
|
34
33
|
### Composable actions menu
|
|
35
34
|
|
|
36
35
|
```ts file="./examples/ComposableActionsMenu.tsx"
|
|
37
|
-
|
|
38
36
|
```
|
|
39
37
|
|
|
40
38
|
### Composable simple select
|
|
41
39
|
|
|
42
40
|
```ts file="./examples/ComposableSimpleSelect.tsx"
|
|
43
|
-
|
|
44
41
|
```
|
|
45
42
|
|
|
46
43
|
### Composable drilldown menu
|
|
47
44
|
|
|
48
45
|
```ts isBeta file="./examples/ComposableDrilldownMenu.tsx"
|
|
49
|
-
|
|
50
46
|
```
|
|
51
47
|
|
|
52
48
|
### Composable tree view menu
|
|
53
49
|
|
|
54
50
|
```ts file="./examples/ComposableTreeViewMenu.tsx"
|
|
55
|
-
|
|
56
51
|
```
|
|
57
52
|
|
|
58
53
|
### Composable flyout
|
|
@@ -60,29 +55,29 @@ Composable menus currently require consumer keyboard handling and use of our und
|
|
|
60
55
|
The flyout will automatically position to the left or top if it would otherwise go outside the window. The menu must be placed in a container outside the main content like Popper, [Popover](/components/popover) or [Tooltip](/components/tooltip) since it may go over the side nav.
|
|
61
56
|
|
|
62
57
|
```ts isBeta file="./examples/ComposableFlyout.tsx"
|
|
63
|
-
|
|
64
58
|
```
|
|
65
59
|
|
|
66
60
|
### Composable application launcher
|
|
67
61
|
|
|
68
62
|
```ts file="./examples/ComposableApplicationLauncher.tsx"
|
|
69
|
-
|
|
70
63
|
```
|
|
71
64
|
|
|
72
65
|
### Composable context selector
|
|
73
66
|
|
|
74
67
|
```ts file="./examples/ComposableContextSelector.tsx"
|
|
75
|
-
|
|
76
68
|
```
|
|
77
69
|
|
|
78
70
|
### Composable options menu variants
|
|
79
71
|
|
|
80
72
|
```ts file="./examples/ComposableOptionsMenuVariants.tsx"
|
|
81
|
-
|
|
82
73
|
```
|
|
83
74
|
|
|
84
75
|
### Composable dropdown variants
|
|
85
76
|
|
|
86
77
|
```ts file="./examples/ComposableDropdwnVariants.tsx"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Composable date select
|
|
87
81
|
|
|
82
|
+
```ts file="./examples/ComposableDateSelect.tsx"
|
|
88
83
|
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MenuToggle, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
export const ComposableSimpleDropdown: React.FunctionComponent = () => {
|
|
5
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
6
|
+
const toggleRef = React.useRef<HTMLButtonElement>();
|
|
7
|
+
const menuRef = React.useRef<HTMLDivElement>();
|
|
8
|
+
const [selected, setSelected] = React.useState<number>(0);
|
|
9
|
+
|
|
10
|
+
const handleMenuKeys = (event: KeyboardEvent) => {
|
|
11
|
+
if (!isOpen) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (menuRef.current.contains(event.target as Node) || toggleRef.current.contains(event.target as Node)) {
|
|
15
|
+
if (event.key === 'Escape' || event.key === 'Tab') {
|
|
16
|
+
setIsOpen(!isOpen);
|
|
17
|
+
toggleRef.current.focus();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
23
|
+
if (isOpen && !menuRef.current.contains(event.target as Node)) {
|
|
24
|
+
setIsOpen(false);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
window.addEventListener('keydown', handleMenuKeys);
|
|
30
|
+
window.addEventListener('click', handleClickOutside);
|
|
31
|
+
return () => {
|
|
32
|
+
window.removeEventListener('keydown', handleMenuKeys);
|
|
33
|
+
window.removeEventListener('click', handleClickOutside);
|
|
34
|
+
};
|
|
35
|
+
}, [isOpen, menuRef]);
|
|
36
|
+
|
|
37
|
+
const onToggleClick = (ev: React.MouseEvent) => {
|
|
38
|
+
ev.stopPropagation(); // Stop handleClickOutside from handling
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
if (menuRef.current) {
|
|
41
|
+
const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');
|
|
42
|
+
firstElement && (firstElement as HTMLElement).focus();
|
|
43
|
+
}
|
|
44
|
+
}, 0);
|
|
45
|
+
setIsOpen(!isOpen);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const monthStrings = [
|
|
49
|
+
'January',
|
|
50
|
+
'February',
|
|
51
|
+
'March',
|
|
52
|
+
'April',
|
|
53
|
+
'May',
|
|
54
|
+
'June',
|
|
55
|
+
'July',
|
|
56
|
+
'August',
|
|
57
|
+
'September',
|
|
58
|
+
'October',
|
|
59
|
+
'November',
|
|
60
|
+
'December'
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const dateString = (date: Date) => `${monthStrings[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
|
|
64
|
+
|
|
65
|
+
const date = new Date();
|
|
66
|
+
|
|
67
|
+
const toggleText = {
|
|
68
|
+
0: 'Today ',
|
|
69
|
+
1: 'Yesterday ',
|
|
70
|
+
2: 'Last 7 days ',
|
|
71
|
+
3: 'Last 14 days '
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const dateText = {
|
|
75
|
+
0: <small className="pf-u-color-200">({dateString(date)})</small>,
|
|
76
|
+
1: (
|
|
77
|
+
<small className="pf-u-color-200">
|
|
78
|
+
({dateString(new Date(new Date().setDate(date.getDate() - 1)))} - {dateString(date)})
|
|
79
|
+
</small>
|
|
80
|
+
),
|
|
81
|
+
2: (
|
|
82
|
+
<small className="pf-u-color-200">
|
|
83
|
+
({dateString(new Date(new Date().setDate(date.getDate() - 7)))} - {dateString(date)})
|
|
84
|
+
</small>
|
|
85
|
+
),
|
|
86
|
+
3: (
|
|
87
|
+
<small className="pf-u-color-200">
|
|
88
|
+
({dateString(new Date(new Date().setDate(date.getDate() - 14)))} - {dateString(date)})
|
|
89
|
+
</small>
|
|
90
|
+
)
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const toggle = (
|
|
94
|
+
<MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen} style={{ minWidth: '250px' }}>
|
|
95
|
+
<span style={{ verticalAlign: 'middle', marginRight: '8px' }}>{toggleText[selected]}</span>
|
|
96
|
+
{dateText[selected]}
|
|
97
|
+
</MenuToggle>
|
|
98
|
+
);
|
|
99
|
+
const menu = (
|
|
100
|
+
// eslint-disable-next-line no-console
|
|
101
|
+
<Menu ref={menuRef} onSelect={(_ev, itemId) => setSelected(itemId as number)} selected={selected}>
|
|
102
|
+
<MenuContent>
|
|
103
|
+
<MenuList>
|
|
104
|
+
<MenuItem itemId={0}>Today</MenuItem>
|
|
105
|
+
<MenuItem itemId={1}>Yesterday</MenuItem>
|
|
106
|
+
<MenuItem itemId={2}>Last 7 days</MenuItem>
|
|
107
|
+
<MenuItem itemId={3}>Last 14 days</MenuItem>
|
|
108
|
+
</MenuList>
|
|
109
|
+
</MenuContent>
|
|
110
|
+
</Menu>
|
|
111
|
+
);
|
|
112
|
+
return <Popper trigger={toggle} popper={menu} isVisible={isOpen} popperMatchesTriggerWidth={false} />;
|
|
113
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: File upload - multiple
|
|
3
|
+
section: components
|
|
4
|
+
beta: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon';
|
|
8
|
+
|
|
9
|
+
## Demos
|
|
10
|
+
|
|
11
|
+
### Rejected file handling
|
|
12
|
+
|
|
13
|
+
This demo shows how to add a modal to alert users that the file(s) they attempted to drop was of a non-acceptable type.
|
|
14
|
+
|
|
15
|
+
```ts file="./examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx"
|
|
16
|
+
```
|
package/src/demos/TileDemo.md
CHANGED
|
@@ -13,11 +13,11 @@ import { Tile } from '@patternfly/react-core';
|
|
|
13
13
|
|
|
14
14
|
const TileSingleSelect: React.FunctionComponent = () => {
|
|
15
15
|
const [selectedId, setSelectedId] = React.useState<string>('');
|
|
16
|
-
|
|
17
|
-
const onSelect = (event: React.MouseEvent) => {
|
|
16
|
+
|
|
17
|
+
const onSelect = (event: React.MouseEvent) => {
|
|
18
18
|
setSelectedId(event.currentTarget.id);
|
|
19
19
|
};
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
const onKeyDown = (event: React.KeyboardEvent) => {
|
|
22
22
|
if (event.key === ' ' || event.key === 'Enter') {
|
|
23
23
|
event.preventDefault();
|
|
@@ -26,32 +26,14 @@ const TileSingleSelect: React.FunctionComponent = () => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<div>
|
|
30
|
-
<Tile
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
onKeyDown={onKeyDown}
|
|
35
|
-
isSelected={selectedId === 'tile-1'}
|
|
36
|
-
/>
|
|
37
|
-
<Tile
|
|
38
|
-
title="Tile 2"
|
|
39
|
-
id="tile-2"
|
|
40
|
-
onClick={onSelect}
|
|
41
|
-
onKeyDown={onKeyDown}
|
|
42
|
-
isSelected={selectedId === 'tile-2'}
|
|
43
|
-
/>
|
|
44
|
-
<Tile title="Tile 3" id="tile-3" isDisabled />
|
|
45
|
-
<Tile
|
|
46
|
-
title="Tile 4"
|
|
47
|
-
id="tile-4"
|
|
48
|
-
onClick={onSelect}
|
|
49
|
-
onKeyDown={onKeyDown}
|
|
50
|
-
isSelected={selectedId === 'tile-4'}
|
|
51
|
-
/>
|
|
29
|
+
<div role="listbox" aria-label="Single selection tiles">
|
|
30
|
+
<Tile title="Tile 1" id="tile-1" onClick={onSelect} onKeyDown={onKeyDown} isSelected={selectedId === 'tile-1'} />
|
|
31
|
+
<Tile title="Tile 2" id="tile-2" onClick={onSelect} onKeyDown={onKeyDown} isSelected={selectedId === 'tile-2'} />
|
|
32
|
+
<Tile title="Tile 3" id="tile-3" isDisabled isSelected={selectedId === 'tile-3'} />
|
|
33
|
+
<Tile title="Tile 4" id="tile-4" onClick={onSelect} onKeyDown={onKeyDown} isSelected={selectedId === 'tile-4'} />
|
|
52
34
|
</div>
|
|
53
35
|
);
|
|
54
|
-
}
|
|
36
|
+
};
|
|
55
37
|
```
|
|
56
38
|
|
|
57
39
|
### Tiles with multiple selection
|
|
@@ -62,18 +44,18 @@ import { Tile } from '@patternfly/react-core';
|
|
|
62
44
|
|
|
63
45
|
const TileMultiSelect: React.FunctionComponent = () => {
|
|
64
46
|
const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
|
|
65
|
-
|
|
47
|
+
|
|
66
48
|
const onSelect = (event: React.MouseEvent | React.KeyboardEvent) => {
|
|
67
49
|
const targetId = event.currentTarget.id;
|
|
68
50
|
setSelectedIds(prevSelectedIds => {
|
|
69
|
-
const newSelectedIds = prevSelectedIds.includes(targetId)
|
|
70
|
-
prevSelectedIds.filter(id => id !== targetId)
|
|
71
|
-
[...prevSelectedIds, targetId]
|
|
51
|
+
const newSelectedIds = prevSelectedIds.includes(targetId)
|
|
52
|
+
? prevSelectedIds.filter(id => id !== targetId)
|
|
53
|
+
: [...prevSelectedIds, targetId];
|
|
72
54
|
console.log('tile selections: ', newSelectedIds);
|
|
73
55
|
return newSelectedIds;
|
|
74
56
|
});
|
|
75
57
|
};
|
|
76
|
-
|
|
58
|
+
|
|
77
59
|
const onKeyDown = (event: React.KeyboardEvent) => {
|
|
78
60
|
console.log(event.key);
|
|
79
61
|
if (event.key === ' ' || event.key === 'Enter') {
|
|
@@ -81,9 +63,9 @@ const TileMultiSelect: React.FunctionComponent = () => {
|
|
|
81
63
|
onSelect(event);
|
|
82
64
|
}
|
|
83
65
|
};
|
|
84
|
-
|
|
66
|
+
|
|
85
67
|
return (
|
|
86
|
-
<div>
|
|
68
|
+
<div role="listbox" aria-multiselectable={true} aria-label="Multiselectable tiles">
|
|
87
69
|
<Tile
|
|
88
70
|
title="Tile 1"
|
|
89
71
|
id="tile-1"
|
|
@@ -108,5 +90,5 @@ const TileMultiSelect: React.FunctionComponent = () => {
|
|
|
108
90
|
/>
|
|
109
91
|
</div>
|
|
110
92
|
);
|
|
111
|
-
}
|
|
93
|
+
};
|
|
112
94
|
```
|
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import {
|
|
3
3
|
MultipleFileUpload,
|
|
4
|
-
MultipleFileUploadInfo,
|
|
5
4
|
MultipleFileUploadMain,
|
|
6
|
-
MultipleFileUploadTitle,
|
|
7
|
-
MultipleFileUploadTitleIcon,
|
|
8
|
-
MultipleFileUploadTitleText,
|
|
9
|
-
MultipleFileUploadTitleTextSeparator,
|
|
10
|
-
MultipleFileUploadButton,
|
|
11
5
|
MultipleFileUploadStatus,
|
|
12
6
|
MultipleFileUploadStatusItem,
|
|
13
|
-
Modal
|
|
7
|
+
Modal,
|
|
8
|
+
Checkbox
|
|
14
9
|
} from '@patternfly/react-core';
|
|
15
|
-
import
|
|
16
|
-
import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon';
|
|
17
|
-
import TimesCircleIcon from '@patternfly/react-icons/dist/esm/icons/times-circle-icon';
|
|
10
|
+
import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon';
|
|
18
11
|
|
|
19
12
|
interface readFile {
|
|
20
13
|
fileName: string;
|
|
@@ -24,9 +17,11 @@ interface readFile {
|
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
export const MultipleFileUploadBasic: React.FunctionComponent = () => {
|
|
20
|
+
const [isHorizontal, setIsHorizontal] = React.useState(false);
|
|
27
21
|
const [currentFiles, setCurrentFiles] = React.useState<File[]>([]);
|
|
28
22
|
const [readFileData, setReadFileData] = React.useState<readFile[]>([]);
|
|
29
23
|
const [showStatus, setShowStatus] = React.useState(false);
|
|
24
|
+
const [statusIcon, setStatusIcon] = React.useState('inProgress');
|
|
30
25
|
const [modalText, setModalText] = React.useState('');
|
|
31
26
|
|
|
32
27
|
// only show the status component once a file has been uploaded, but keep the status list component itself even if all files are removed
|
|
@@ -35,17 +30,15 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => {
|
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
// determine the icon that should be shown for the overall status list
|
|
38
|
-
|
|
33
|
+
React.useEffect(() => {
|
|
39
34
|
if (readFileData.length < currentFiles.length) {
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
setStatusIcon('inProgress');
|
|
36
|
+
} else if (readFileData.every(file => file.loadResult === 'success')) {
|
|
37
|
+
setStatusIcon('success');
|
|
38
|
+
} else {
|
|
39
|
+
setStatusIcon('danger');
|
|
45
40
|
}
|
|
46
|
-
|
|
47
|
-
return <TimesCircleIcon />;
|
|
48
|
-
};
|
|
41
|
+
}, [readFileData, currentFiles]);
|
|
49
42
|
|
|
50
43
|
// remove files from both state arrays based on their name
|
|
51
44
|
const removeFiles = (namesOfFilesToRemove: string[]) => {
|
|
@@ -101,51 +94,54 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => {
|
|
|
101
94
|
const successfullyReadFileCount = readFileData.filter(fileData => fileData.loadResult === 'success').length;
|
|
102
95
|
|
|
103
96
|
return (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
<MultipleFileUploadMain>
|
|
113
|
-
<MultipleFileUploadTitle>
|
|
114
|
-
<MultipleFileUploadTitleIcon />
|
|
115
|
-
<MultipleFileUploadTitleText>
|
|
116
|
-
Drag and drop files here
|
|
117
|
-
<MultipleFileUploadTitleTextSeparator>or</MultipleFileUploadTitleTextSeparator>
|
|
118
|
-
</MultipleFileUploadTitleText>
|
|
119
|
-
</MultipleFileUploadTitle>
|
|
120
|
-
<MultipleFileUploadButton />
|
|
121
|
-
<MultipleFileUploadInfo>Accepted file types: JPEG, Doc, PDF, PNG</MultipleFileUploadInfo>
|
|
122
|
-
</MultipleFileUploadMain>
|
|
123
|
-
{showStatus && (
|
|
124
|
-
<MultipleFileUploadStatus
|
|
125
|
-
statusToggleText={`${successfullyReadFileCount} of ${currentFiles.length} files uploaded`}
|
|
126
|
-
statusToggleIcon={getStatusIcon()}
|
|
127
|
-
>
|
|
128
|
-
{currentFiles.map(file => (
|
|
129
|
-
<MultipleFileUploadStatusItem
|
|
130
|
-
file={file}
|
|
131
|
-
key={file.name}
|
|
132
|
-
onClearClick={() => removeFiles([file.name])}
|
|
133
|
-
onReadSuccess={handleReadSuccess}
|
|
134
|
-
onReadFail={handleReadFail}
|
|
135
|
-
/>
|
|
136
|
-
))}
|
|
137
|
-
</MultipleFileUploadStatus>
|
|
138
|
-
)}
|
|
139
|
-
<Modal
|
|
140
|
-
isOpen={!!modalText}
|
|
141
|
-
title="Unsupported file"
|
|
142
|
-
titleIconVariant="warning"
|
|
143
|
-
showClose
|
|
144
|
-
aria-label="unsupported file upload attempted"
|
|
145
|
-
onClose={() => setModalText('')}
|
|
97
|
+
<>
|
|
98
|
+
<MultipleFileUpload
|
|
99
|
+
onFileDrop={handleFileDrop}
|
|
100
|
+
dropzoneProps={{
|
|
101
|
+
accept: 'image/jpeg, application/msword, application/pdf, image/png',
|
|
102
|
+
onDropRejected: handleDropRejected
|
|
103
|
+
}}
|
|
104
|
+
isHorizontal={isHorizontal}
|
|
146
105
|
>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
106
|
+
<MultipleFileUploadMain
|
|
107
|
+
titleIcon={<UploadIcon />}
|
|
108
|
+
titleText="Drag and drop files here"
|
|
109
|
+
titleTextSeparator="or"
|
|
110
|
+
infoText="Accepted file types: JPEG, Doc, PDF, PNG"
|
|
111
|
+
/>
|
|
112
|
+
{showStatus && (
|
|
113
|
+
<MultipleFileUploadStatus
|
|
114
|
+
statusToggleText={`${successfullyReadFileCount} of ${currentFiles.length} files uploaded`}
|
|
115
|
+
statusToggleIcon={statusIcon}
|
|
116
|
+
>
|
|
117
|
+
{currentFiles.map(file => (
|
|
118
|
+
<MultipleFileUploadStatusItem
|
|
119
|
+
file={file}
|
|
120
|
+
key={file.name}
|
|
121
|
+
onClearClick={() => removeFiles([file.name])}
|
|
122
|
+
onReadSuccess={handleReadSuccess}
|
|
123
|
+
onReadFail={handleReadFail}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</MultipleFileUploadStatus>
|
|
127
|
+
)}
|
|
128
|
+
<Modal
|
|
129
|
+
isOpen={!!modalText}
|
|
130
|
+
title="Unsupported file"
|
|
131
|
+
titleIconVariant="warning"
|
|
132
|
+
showClose
|
|
133
|
+
aria-label="unsupported file upload attempted"
|
|
134
|
+
onClose={() => setModalText('')}
|
|
135
|
+
>
|
|
136
|
+
{modalText}
|
|
137
|
+
</Modal>
|
|
138
|
+
</MultipleFileUpload>
|
|
139
|
+
<Checkbox
|
|
140
|
+
id="horizontal-checkbox"
|
|
141
|
+
label="Show as horizontal"
|
|
142
|
+
isChecked={isHorizontal}
|
|
143
|
+
onChange={() => setIsHorizontal(!isHorizontal)}
|
|
144
|
+
/>
|
|
145
|
+
</>
|
|
150
146
|
);
|
|
151
147
|
};
|