@react-ui-org/react-ui 0.47.0 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. package/dist/lib.development.js +465 -93
  2. package/dist/lib.js +1 -1
  3. package/package.json +1 -1
  4. package/src/lib/components/Alert/Alert.jsx +3 -0
  5. package/src/lib/components/Alert/Alert.scss +10 -10
  6. package/src/lib/components/Alert/README.mdx +18 -2
  7. package/src/lib/components/Alert/index.js +1 -1
  8. package/src/lib/components/Badge/Badge.jsx +4 -8
  9. package/src/lib/components/Badge/Badge.scss +21 -21
  10. package/src/lib/components/Badge/README.mdx +15 -1
  11. package/src/lib/components/Badge/index.js +1 -1
  12. package/src/lib/components/Button/Button.jsx +23 -34
  13. package/src/lib/components/Button/README.mdx +21 -7
  14. package/src/lib/components/Button/_base.scss +20 -20
  15. package/src/lib/components/Button/_priorities.scss +35 -35
  16. package/src/lib/components/Button/helpers/getRootLabelVisibilityClassName.js +7 -7
  17. package/src/lib/components/Button/helpers/getRootPriorityClassName.js +3 -3
  18. package/src/lib/components/Button/index.js +1 -1
  19. package/src/lib/components/ButtonGroup/ButtonGroup.jsx +2 -8
  20. package/src/lib/components/ButtonGroup/README.mdx +18 -2
  21. package/src/lib/components/Card/Card.jsx +6 -10
  22. package/src/lib/components/Card/Card.scss +13 -13
  23. package/src/lib/components/Card/CardBody.jsx +6 -10
  24. package/src/lib/components/Card/CardFooter.jsx +6 -7
  25. package/src/lib/components/Card/README.mdx +21 -5
  26. package/src/lib/components/CheckboxField/CheckboxField.jsx +17 -44
  27. package/src/lib/components/CheckboxField/README.mdx +18 -6
  28. package/src/lib/components/CheckboxField/index.js +1 -1
  29. package/src/lib/components/FileInputField/FileInputField.jsx +20 -29
  30. package/src/lib/components/FileInputField/FileInputField.scss +3 -3
  31. package/src/lib/components/FileInputField/README.mdx +30 -28
  32. package/src/lib/components/FileInputField/index.js +1 -1
  33. package/src/lib/components/FormLayout/FormLayout.jsx +5 -9
  34. package/src/lib/components/FormLayout/FormLayout.scss +3 -3
  35. package/src/lib/components/FormLayout/FormLayoutCustomField.jsx +4 -1
  36. package/src/lib/components/FormLayout/FormLayoutCustomField.scss +8 -8
  37. package/src/lib/components/FormLayout/README.mdx +28 -13
  38. package/src/lib/components/Grid/Grid.jsx +31 -35
  39. package/src/lib/components/Grid/Grid.scss +10 -15
  40. package/src/lib/components/Grid/GridSpan.jsx +5 -11
  41. package/src/lib/components/Grid/README.mdx +48 -36
  42. package/src/lib/components/Grid/_helpers/generateResponsiveCustomProperties.js +11 -3
  43. package/src/lib/components/Grid/_settings.scss +18 -0
  44. package/src/lib/components/Grid/_tools.scss +5 -5
  45. package/src/lib/components/Modal/Modal.jsx +147 -254
  46. package/src/lib/components/Modal/Modal.scss +7 -55
  47. package/src/lib/components/Modal/ModalBody.jsx +60 -0
  48. package/src/lib/components/Modal/ModalBody.scss +18 -0
  49. package/src/lib/components/Modal/ModalCloseButton.jsx +45 -0
  50. package/src/lib/components/Modal/ModalCloseButton.scss +18 -0
  51. package/src/lib/components/Modal/ModalContent.jsx +39 -0
  52. package/src/lib/components/Modal/ModalContent.scss +5 -0
  53. package/src/lib/components/Modal/ModalFooter.jsx +42 -0
  54. package/src/lib/components/Modal/ModalFooter.scss +35 -0
  55. package/src/lib/components/Modal/ModalHeader.jsx +44 -0
  56. package/src/lib/components/Modal/ModalHeader.scss +30 -0
  57. package/src/lib/components/Modal/ModalTitle.jsx +44 -0
  58. package/src/lib/components/Modal/ModalTitle.scss +10 -0
  59. package/src/lib/components/Modal/README.mdx +865 -195
  60. package/src/lib/components/Modal/_helpers/getJustifyClassName.js +19 -0
  61. package/src/lib/components/Modal/_helpers/getScrollingClassName.js +11 -0
  62. package/src/lib/components/Modal/_settings.scss +1 -5
  63. package/src/lib/components/Modal/_theme.scss +6 -0
  64. package/src/lib/components/Modal/index.js +7 -1
  65. package/src/lib/components/Paper/Paper.jsx +5 -9
  66. package/src/lib/components/Paper/Paper.scss +2 -2
  67. package/src/lib/components/Paper/README.mdx +15 -1
  68. package/src/lib/components/Paper/index.js +1 -1
  69. package/src/lib/components/Popover/Popover.jsx +14 -30
  70. package/src/lib/components/Popover/Popover.scss +7 -6
  71. package/src/lib/components/Popover/PopoverWrapper.jsx +5 -12
  72. package/src/lib/components/Popover/PopoverWrapper.scss +3 -0
  73. package/src/lib/components/Popover/README.mdx +32 -11
  74. package/src/lib/components/Popover/_theme.scss +1 -1
  75. package/src/lib/components/Radio/README.mdx +13 -6
  76. package/src/lib/components/Radio/Radio.jsx +39 -29
  77. package/src/lib/components/Radio/Radio.scss +3 -3
  78. package/src/lib/components/Radio/index.js +1 -1
  79. package/src/lib/components/ScrollView/README.mdx +165 -84
  80. package/src/lib/components/ScrollView/ScrollView.jsx +115 -117
  81. package/src/lib/components/ScrollView/ScrollView.scss +18 -16
  82. package/src/lib/components/ScrollView/index.js +1 -1
  83. package/src/lib/components/SelectField/README.mdx +83 -7
  84. package/src/lib/components/SelectField/SelectField.jsx +86 -61
  85. package/src/lib/components/SelectField/SelectField.scss +8 -8
  86. package/src/lib/components/SelectField/_components/Option/Option.jsx +46 -0
  87. package/src/lib/components/SelectField/_components/Option/index.js +1 -0
  88. package/src/lib/components/SelectField/index.js +1 -1
  89. package/src/lib/components/Table/README.mdx +25 -9
  90. package/src/lib/components/Table/Table.jsx +43 -101
  91. package/src/lib/components/Table/Table.scss +0 -24
  92. package/src/lib/components/Table/_components/TableBodyCell/TableBodyCell.jsx +46 -0
  93. package/src/lib/components/Table/_components/TableBodyCell/index.js +1 -0
  94. package/src/lib/components/Table/_components/TableCell.scss +25 -0
  95. package/src/lib/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx +71 -0
  96. package/src/lib/components/Table/_components/TableHeaderCell/index.js +1 -0
  97. package/src/lib/components/Table/index.js +1 -1
  98. package/src/lib/components/Tabs/README.mdx +21 -3
  99. package/src/lib/components/Tabs/Tabs.jsx +6 -1
  100. package/src/lib/components/Tabs/TabsItem.jsx +3 -0
  101. package/src/lib/components/Tabs/TabsItem.scss +1 -2
  102. package/src/lib/components/Text/README.mdx +25 -7
  103. package/src/lib/components/Text/Text.jsx +3 -7
  104. package/src/lib/components/Text/Text.scss +6 -6
  105. package/src/lib/components/Text/_helpers/getRootClampClassName.js +2 -2
  106. package/src/lib/components/Text/_helpers/getRootHyphensClassName.js +2 -2
  107. package/src/lib/components/Text/_helpers/getRootWordWrappingClassName.js +2 -2
  108. package/src/lib/components/Text/index.js +1 -1
  109. package/src/lib/components/TextArea/README.mdx +34 -31
  110. package/src/lib/components/TextArea/TextArea.jsx +23 -63
  111. package/src/lib/components/TextArea/TextArea.scss +8 -8
  112. package/src/lib/components/TextArea/index.js +1 -1
  113. package/src/lib/components/TextField/README.mdx +56 -54
  114. package/src/lib/components/TextField/TextField.jsx +25 -52
  115. package/src/lib/components/TextField/TextField.scss +9 -9
  116. package/src/lib/components/TextField/index.js +1 -1
  117. package/src/lib/components/TextLink/README.mdx +13 -6
  118. package/src/lib/components/TextLink/TextLink.jsx +0 -10
  119. package/src/lib/components/TextLink/index.js +1 -1
  120. package/src/lib/components/Toggle/README.mdx +18 -6
  121. package/src/lib/components/Toggle/Toggle.jsx +18 -44
  122. package/src/lib/components/Toggle/index.js +1 -1
  123. package/src/lib/components/Toolbar/README.mdx +21 -6
  124. package/src/lib/components/Toolbar/Toolbar.jsx +9 -43
  125. package/src/lib/components/Toolbar/Toolbar.scss +24 -12
  126. package/src/lib/components/Toolbar/ToolbarGroup.jsx +7 -26
  127. package/src/lib/components/Toolbar/ToolbarItem.jsx +3 -7
  128. package/src/lib/components/Toolbar/_helpers/getAlignClassName.js +19 -0
  129. package/src/lib/components/Toolbar/_helpers/getJustifyClassName.js +16 -0
  130. package/src/lib/components/_helpers/getRootColorClassName.js +10 -10
  131. package/src/lib/components/_helpers/getRootSizeClassName.js +3 -3
  132. package/src/lib/components/_helpers/transferProps.js +1 -1
  133. package/src/lib/index.js +24 -16
  134. package/src/lib/provider/withGlobalProps.jsx +20 -3
  135. package/src/lib/styles/tools/form-fields/_box-field-layout.scss +15 -15
  136. package/src/lib/styles/tools/form-fields/_inline-field-elements.scss +1 -1
  137. package/src/lib/styles/tools/form-fields/_inline-field-layout.scss +9 -9
  138. package/src/lib/theme.scss +18 -26
  139. package/src/lib/translations/en.js +1 -1
  140. package/src/lib/components/Grid/_theme.scss +0 -11
  141. package/src/lib/components/ScrollView/_theme.scss +0 -2
  142. package/src/lib/components/withForwardedRef.jsx +0 -11
@@ -0,0 +1,71 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { Button } from '../../../..';
4
+ import styles from '../TableCell.scss';
5
+
6
+ export const TableHeaderCell = ({
7
+ column,
8
+ id,
9
+ sort,
10
+ }) => {
11
+ const sortDirection = sort && column.name === sort.column ? sort.direction : 'asc';
12
+ const isSortingActive = sort && column.name === sort.column;
13
+
14
+ return (
15
+ <th
16
+ className={isSortingActive ? styles.isTableHeadCellSortingActive : styles.tableHeadCell}
17
+ id={id}
18
+ >
19
+ {sort && column.isSortable && (
20
+ <div className={styles.sortButton}>
21
+ <Button
22
+ beforeLabel={
23
+ sortDirection === 'asc'
24
+ ? sort.ascendingIcon
25
+ : sort.descendingIcon
26
+ }
27
+ id={id && `${id}__sortButton`}
28
+ label={sortDirection}
29
+ labelVisibility="none"
30
+ onClick={() => sort.onClick(column.name, sortDirection)}
31
+ priority="flat"
32
+ />
33
+ </div>
34
+ )}
35
+ {column.label}
36
+ </th>
37
+ );
38
+ };
39
+
40
+ TableHeaderCell.defaultProps = {
41
+ id: undefined,
42
+ sort: null,
43
+ };
44
+
45
+ TableHeaderCell.propTypes = {
46
+ /**
47
+ * Table data column, optionally sortable. The `format` function can be used to process the
48
+ * column data before displaying them.
49
+ */
50
+ column: PropTypes.shape({
51
+ isSortable: PropTypes.bool,
52
+ label: PropTypes.string,
53
+ name: PropTypes.string.isRequired,
54
+ }).isRequired,
55
+ /**
56
+ * ID of the HTML <th> element and nested button for sorting.
57
+ */
58
+ id: PropTypes.string,
59
+ /**
60
+ * Sorting configuration required to make columns sortable.
61
+ */
62
+ sort: PropTypes.shape({
63
+ ascendingIcon: PropTypes.node.isRequired,
64
+ column: PropTypes.string.isRequired,
65
+ descendingIcon: PropTypes.node.isRequired,
66
+ direction: PropTypes.oneOf(['asc', 'desc']).isRequired,
67
+ onClick: PropTypes.func.isRequired,
68
+ }),
69
+ };
70
+
71
+ export default TableHeaderCell;
@@ -0,0 +1 @@
1
+ export { default as TableHeaderCell } from './TableHeaderCell';
@@ -1 +1 @@
1
- export { default } from './Table';
1
+ export { default as Table } from './Table';
@@ -11,9 +11,11 @@ import {
11
11
  Props,
12
12
  } from 'docz'
13
13
  import { Icon } from '../../../docs/_components/Icon/Icon'
14
- import ScrollView from '../ScrollView'
15
- import { Tabs } from './Tabs'
16
- import { TabsItem } from './TabsItem'
14
+ import {
15
+ ScrollView,
16
+ Tabs,
17
+ TabsItem,
18
+ } from '../..'
17
19
 
18
20
  Tabs separate related content into groups within a single context.
19
21
 
@@ -169,6 +171,18 @@ accessible no matter the space they have around. Wrap Tabs into
169
171
  }}
170
172
  </Playground>
171
173
 
174
+ ## Forwarding HTML Attributes
175
+
176
+ In addition to the options below in the [component's API](#api) section, you
177
+ can specify [React synthetic events] or **any HTML attribute you like.** All
178
+ attributes that don't interfere with the API are forwarded to the `<nav>` HTML
179
+ element in case of `Tabs` component and to the `<li>` HTML element in
180
+ case of `TabsItem`. This enables making the component interactive and helps
181
+ to improve its accessibility.
182
+
183
+ 👉 Refer to the MDN reference for the full list of supported attributes of the
184
+ [nav] and [li] element.
185
+
172
186
  ## API
173
187
 
174
188
  <Props table of={Tabs} />
@@ -218,3 +232,7 @@ Where:
218
232
  - `<PROPERTY>` is one of `font-weight`, `color`, `border-width`, `border-color`,
219
233
  `background-color`, `box-shadow`, `shift-y` (shifts vertically the whole
220
234
  item), or `label__shift-y` (tweaks vertical position of tab label).
235
+
236
+ [React synthetic events]: https://reactjs.org/docs/events.html
237
+ [nav]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav#attributes
238
+ [li]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li#attributes
@@ -1,13 +1,18 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { withGlobalProps } from '../../provider';
4
+ import { transferProps } from '../_helpers/transferProps';
4
5
  import styles from './Tabs.scss';
5
6
 
6
7
  export const Tabs = ({
7
8
  children,
8
9
  id,
10
+ ...restProps
9
11
  }) => (
10
- <nav id={id}>
12
+ <nav
13
+ {...transferProps(restProps)}
14
+ id={id}
15
+ >
11
16
  <ul
12
17
  className={styles.list}
13
18
  id={id && `${id}__list`}
@@ -1,6 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { withGlobalProps } from '../../provider';
4
+ import { transferProps } from '../_helpers/transferProps';
4
5
  import { classNames } from '../../utils/classNames';
5
6
  import styles from './TabsItem.scss';
6
7
 
@@ -12,8 +13,10 @@ export const TabsItem = ({
12
13
  isActive,
13
14
  label,
14
15
  onClick,
16
+ ...restProps
15
17
  }) => (
16
18
  <li
19
+ {...transferProps(restProps)}
17
20
  className={classNames(
18
21
  styles.root,
19
22
  isActive && styles.isRootActive,
@@ -47,8 +47,7 @@
47
47
  line-height: 1;
48
48
  text-decoration: none;
49
49
  color: theme.$item-color;
50
- border-width: theme.$item-border-width;
51
- border-style: solid;
50
+ border: theme.$item-border-width solid;
52
51
  border-color: theme.$item-border-color;
53
52
  border-top-left-radius: theme.$item-border-radius;
54
53
  border-top-right-radius: theme.$item-border-radius;
@@ -11,13 +11,15 @@ import {
11
11
  Props,
12
12
  } from 'docz'
13
13
  import { Placeholder } from '../../../docs/_components/Placeholder/Placeholder'
14
- import { Toolbar } from '../Toolbar/Toolbar'
15
- import { ToolbarGroup } from '../Toolbar/ToolbarGroup'
16
- import { ToolbarItem } from '../Toolbar/ToolbarItem'
17
- import { Button } from '../Button/Button'
18
- import { ButtonGroup } from '../ButtonGroup/ButtonGroup'
19
- import { TextField } from '../TextField/TextField'
20
- import { Text } from './Text'
14
+ import {
15
+ Button,
16
+ ButtonGroup,
17
+ Text,
18
+ TextField,
19
+ Toolbar,
20
+ ToolbarGroup,
21
+ ToolbarItem,
22
+ } from '../..'
21
23
 
22
24
  Text is a tiny component to control wrapping of text content.
23
25
 
@@ -212,6 +214,22 @@ will override automatic break point selection in `auto` mode when present.
212
214
  }}
213
215
  </Playground>
214
216
 
217
+ ## Forwarding HTML Attributes
218
+
219
+ In addition to the options below in the [component's API](#api) section, you
220
+ can specify [React synthetic events] or **any HTML attribute you like.** All
221
+ attributes that don't interfere with the API are forwarded either to the
222
+ `<span>` or to the `<div>` HTML element in case that `blockLevel` is set to
223
+ `true`. This enables making the component interactive and helps to improve its
224
+ accessibility.
225
+
226
+ 👉 Refer to the MDN reference for the full list of supported attributes of the
227
+ [span] and [div] element.
228
+
215
229
  ## API
216
230
 
217
231
  <Props table of={Text} />
232
+
233
+ [React synthetic events]: https://reactjs.org/docs/events.html
234
+ [span]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span#attributes
235
+ [div]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
@@ -1,6 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { withGlobalProps } from '../../provider';
4
+ import { transferProps } from '../_helpers/transferProps';
4
5
  import { classNames } from '../../utils/classNames';
5
6
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
6
7
  import { getRootClampClassName } from './_helpers/getRootClampClassName';
@@ -12,9 +13,9 @@ export const Text = ({
12
13
  blockLevel,
13
14
  children,
14
15
  hyphens,
15
- id,
16
16
  lines,
17
17
  wordWrapping,
18
+ ...restProps
18
19
  }) => {
19
20
  if (isChildrenEmpty(children)) {
20
21
  return null;
@@ -24,6 +25,7 @@ export const Text = ({
24
25
 
25
26
  return (
26
27
  <HtmlElement
28
+ {...transferProps(restProps)}
27
29
  className={(hyphens !== 'none' || lines > 0 || wordWrapping !== 'normal')
28
30
  ? classNames(
29
31
  getRootClampClassName(lines, styles),
@@ -31,7 +33,6 @@ export const Text = ({
31
33
  getRootWordWrappingClassName(wordWrapping, styles),
32
34
  )
33
35
  : undefined}
34
- id={id}
35
36
  style={(lines > 1) ? { '--rui-custom-lines': lines } : undefined}
36
37
  >
37
38
  {children}
@@ -43,7 +44,6 @@ Text.defaultProps = {
43
44
  blockLevel: false,
44
45
  children: null,
45
46
  hyphens: 'none',
46
- id: undefined,
47
47
  lines: undefined,
48
48
  wordWrapping: 'normal',
49
49
  };
@@ -61,10 +61,6 @@ Text.propTypes = {
61
61
  * Turn on hyphenation. Head to [Hyphens](#hyphens) to learn more.
62
62
  */
63
63
  hyphens: PropTypes.oneOf(['none', 'auto', 'manual']),
64
- /**
65
- * Optional ID of the root HTML element.
66
- */
67
- id: PropTypes.string,
68
64
  /**
69
65
  * Optional number of lines. If exceeded, the content is truncated and appended by an ellipsis (`…`).
70
66
  */
@@ -5,7 +5,7 @@
5
5
  // 2. Different approaches are used for single and multiline texts because the latter approach
6
6
  // doesn't always work for single-line texts.
7
7
 
8
- .rootClampSingleLine {
8
+ .isRootClampSingleLine {
9
9
  display: block; // 2.
10
10
  overflow: hidden;
11
11
  text-overflow: ellipsis;
@@ -13,7 +13,7 @@
13
13
  }
14
14
 
15
15
  // stylelint-disable property-no-vendor-prefix, value-no-vendor-prefix
16
- .rootClampMultiLine {
16
+ .isRootClampMultiLine {
17
17
  display: -webkit-box; // 2.
18
18
  -webkit-line-clamp: var(--rui-custom-lines);
19
19
  -webkit-box-orient: vertical;
@@ -22,19 +22,19 @@
22
22
  }
23
23
  // stylelint-enable property-no-vendor-prefix, value-no-vendor-prefix
24
24
 
25
- .rootHyphensAuto {
25
+ .isRootHyphensAuto {
26
26
  hyphens: auto;
27
27
  }
28
28
 
29
- .rootHyphensManual {
29
+ .isRootHyphensManual {
30
30
  hyphens: manual;
31
31
  }
32
32
 
33
- .rootWordWrappingAnywhere {
33
+ .isRootWordWrappingAnywhere {
34
34
  word-break: break-all;
35
35
  }
36
36
 
37
- .rootWordWrappingLongWords {
37
+ .isRootWordWrappingLongWords {
38
38
  word-break: break-word; // 1.
39
39
  overflow-wrap: anywhere;
40
40
  }
@@ -1,10 +1,10 @@
1
1
  export const getRootClampClassName = (lines, styles) => {
2
2
  if (lines === 1) {
3
- return styles.rootClampSingleLine;
3
+ return styles.isRootClampSingleLine;
4
4
  }
5
5
 
6
6
  if (lines > 1) {
7
- return styles.rootClampMultiLine;
7
+ return styles.isRootClampMultiLine;
8
8
  }
9
9
 
10
10
  return null;
@@ -1,10 +1,10 @@
1
1
  export const getRootHyphensClassName = (hyphens, styles) => {
2
2
  if (hyphens === 'auto') {
3
- return styles.rootHyphensAuto;
3
+ return styles.isRootHyphensAuto;
4
4
  }
5
5
 
6
6
  if (hyphens === 'manual') {
7
- return styles.rootHyphensManual;
7
+ return styles.isRootHyphensManual;
8
8
  }
9
9
 
10
10
  return null;
@@ -1,10 +1,10 @@
1
1
  export const getRootWordWrappingClassName = (wordWrapping, styles) => {
2
2
  if (wordWrapping === 'anywhere') {
3
- return styles.rootWordWrappingAnywhere;
3
+ return styles.isRootWordWrappingAnywhere;
4
4
  }
5
5
 
6
6
  if (wordWrapping === 'long-words') {
7
- return styles.rootWordWrappingLongWords;
7
+ return styles.isRootWordWrappingLongWords;
8
8
  }
9
9
 
10
10
  return null;
@@ -1 +1 @@
1
- export { default } from './Text';
1
+ export { default as Text } from './Text';
@@ -12,7 +12,7 @@ import {
12
12
  Playground,
13
13
  Props,
14
14
  } from 'docz'
15
- import { TextArea } from './TextArea'
15
+ import { TextArea } from '../..'
16
16
 
17
17
  ## Basic Usage
18
18
 
@@ -142,31 +142,6 @@ to achieve that effect.
142
142
  />
143
143
  </Playground>
144
144
 
145
- ## Forwarding HTML Attributes
146
-
147
- When you want to improve the accessibility of your text fields even further, you
148
- can **add whatever HTML attribute you like.** All attributes that don't
149
- interfere with [component's API](#api) are forwarded to the native HTML input.
150
-
151
- <Playground>
152
- <TextArea
153
- label="Address"
154
- autoComplete="street-address"
155
- minLength={3}
156
- maxLength={80}
157
- />
158
- <TextArea
159
- label="Address"
160
- variant="filled"
161
- autoComplete="street-address"
162
- minLength={3}
163
- maxLength={80}
164
- />
165
- </Playground>
166
-
167
- 👉 Refer to the MDN reference for the full list of
168
- [supported attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#Attributes).
169
-
170
145
  ## Invisible Label
171
146
 
172
147
  In some cases, it may be convenient to visually hide the field label. The label
@@ -346,12 +321,38 @@ It's possible to disable the whole input.
346
321
  />
347
322
  </Playground>
348
323
 
349
- ## API
324
+ ## Forwarding HTML Attributes
350
325
 
351
- In addition to the options below, you can specify [React synthetic events] or
352
- any custom HTML attributes that do not interfere with the API, and they will be
353
- passed to the `<textarea>` HTML element. This enables making the component
354
- interactive and helps improve its [accessibility](#forwarding-html-attributes).
326
+ In addition to the options below in the [component's API](#api) section, you
327
+ can specify [React synthetic events] or you can **add whatever HTML attribute
328
+ you like.** All attributes that don't interfere with the API are forwarded to
329
+ the native HTML `<textarea>`. This enables making the component interactive and
330
+ to helps to improve its accessibility.
331
+
332
+ <Playground>
333
+ <TextArea
334
+ label="Address"
335
+ autoComplete="street-address"
336
+ minLength={3}
337
+ maxLength={80}
338
+ />
339
+ <TextArea
340
+ label="Address"
341
+ variant="filled"
342
+ autoComplete="street-address"
343
+ minLength={3}
344
+ maxLength={80}
345
+ />
346
+ </Playground>
347
+
348
+ 👉 Refer to the MDN reference for the full list of supported attributes of the
349
+ [textarea] element.
350
+
351
+ ## Forwarding ref
352
+
353
+ If you provide [ref], it is forwarded to the native HTML `<textarea>` element.
354
+
355
+ ## API
355
356
 
356
357
  <Props table of={TextArea} />
357
358
 
@@ -361,3 +362,5 @@ Head to [Forms Theming](/customize/theming/forms) to see shared form theming
361
362
  options.
362
363
 
363
364
  [React synthetic events]: https://reactjs.org/docs/events.html
365
+ [textarea]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attributes
366
+ [ref]: https://reactjs.org/docs/refs-and-the-dom.html
@@ -7,29 +7,25 @@ import { getRootValidationStateClassName } from '../_helpers/getRootValidationSt
7
7
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
8
8
  import { transferProps } from '../_helpers/transferProps';
9
9
  import { FormLayoutContext } from '../FormLayout';
10
- import withForwardedRef from '../withForwardedRef';
11
10
  import styles from './TextArea.scss';
12
11
 
13
- export const TextArea = ({
14
- cols,
15
- disabled,
16
- forwardedRef,
17
- fullWidth,
18
- helpText,
19
- id,
20
- isLabelVisible,
21
- label,
22
- layout,
23
- placeholder,
24
- required,
25
- rows,
26
- size,
27
- validationState,
28
- validationText,
29
- value,
30
- variant,
31
- ...restProps
32
- }) => {
12
+ export const TextArea = React.forwardRef((props, ref) => {
13
+ const {
14
+ disabled,
15
+ fullWidth,
16
+ helpText,
17
+ id,
18
+ isLabelVisible,
19
+ label,
20
+ layout,
21
+ required,
22
+ size,
23
+ validationState,
24
+ validationText,
25
+ variant,
26
+ ...restProps
27
+ } = props;
28
+
33
29
  const context = useContext(FormLayoutContext);
34
30
 
35
31
  return (
@@ -39,13 +35,13 @@ export const TextArea = ({
39
35
  fullWidth && styles.isRootFullWidth,
40
36
  context && styles.isRootInFormLayout,
41
37
  resolveContextOrProp(context && context.layout, layout) === 'horizontal'
42
- ? styles.rootLayoutHorizontal
43
- : styles.rootLayoutVertical,
38
+ ? styles.isRootLayoutHorizontal
39
+ : styles.isRootLayoutVertical,
44
40
  disabled && styles.isRootDisabled,
45
41
  required && styles.isRootRequired,
46
42
  getRootSizeClassName(size, styles),
47
43
  getRootValidationStateClassName(validationState, styles),
48
- variant === 'filled' ? styles.rootVariantFilled : styles.rootVariantOutline,
44
+ variant === 'filled' ? styles.isRootVariantFilled : styles.isRootVariantOutline,
49
45
  )}
50
46
  htmlFor={id}
51
47
  id={id && `${id}__label`}
@@ -64,14 +60,10 @@ export const TextArea = ({
64
60
  <textarea
65
61
  {...transferProps(restProps)}
66
62
  className={styles.input}
67
- cols={cols}
68
63
  disabled={disabled}
69
64
  id={id}
70
- placeholder={placeholder}
71
- ref={forwardedRef}
65
+ ref={ref}
72
66
  required={required}
73
- rows={rows}
74
- value={value}
75
67
  />
76
68
  {variant === 'filled' && (
77
69
  <div className={styles.bottomLine} />
@@ -96,44 +88,27 @@ export const TextArea = ({
96
88
  </div>
97
89
  </label>
98
90
  );
99
- };
91
+ });
100
92
 
101
93
  TextArea.defaultProps = {
102
- cols: null,
103
94
  disabled: false,
104
- forwardedRef: undefined,
105
95
  fullWidth: false,
106
96
  helpText: null,
107
97
  id: undefined,
108
98
  isLabelVisible: true,
109
99
  layout: 'vertical',
110
- placeholder: null,
111
100
  required: false,
112
- rows: 3,
113
101
  size: 'medium',
114
102
  validationState: null,
115
103
  validationText: null,
116
- value: undefined,
117
104
  variant: 'outline',
118
105
  };
119
106
 
120
107
  TextArea.propTypes = {
121
- /**
122
- * The number of visible text columns for the control.
123
- */
124
- cols: PropTypes.number,
125
108
  /**
126
109
  * If `true`, the input will be disabled.
127
110
  */
128
111
  disabled: PropTypes.bool,
129
- /**
130
- * Reference forwarded to the `textarea` element.
131
- */
132
- forwardedRef: PropTypes.oneOfType([
133
- PropTypes.func,
134
- // eslint-disable-next-line react/forbid-prop-types
135
- PropTypes.shape({ current: PropTypes.any }),
136
- ]),
137
112
  /**
138
113
  * If `true`, the field will span the full width of its parent.
139
114
  */
@@ -165,18 +140,10 @@ TextArea.propTypes = {
165
140
  * as the value is inherited in such case.
166
141
  */
167
142
  layout: PropTypes.oneOf(['horizontal', 'vertical']),
168
- /**
169
- * Optional example value.
170
- */
171
- placeholder: PropTypes.string,
172
143
  /**
173
144
  * If `true`, the input will be required.
174
145
  */
175
146
  required: PropTypes.bool,
176
- /**
177
- * The number of visible text lines for the control.
178
- */
179
- rows: PropTypes.number,
180
147
  /**
181
148
  * Size of the field.
182
149
  */
@@ -189,19 +156,12 @@ TextArea.propTypes = {
189
156
  * Validation message to be displayed.
190
157
  */
191
158
  validationText: PropTypes.node,
192
- /**
193
- * Value of the input.
194
- */
195
- value: PropTypes.oneOfType([
196
- PropTypes.string,
197
- PropTypes.number,
198
- ]),
199
159
  /**
200
160
  * Design variant of the field, further customizable with CSS custom properties.
201
161
  */
202
162
  variant: PropTypes.oneOf(['filled', 'outline']),
203
163
  };
204
164
 
205
- export const TextAreaWithGlobalProps = withForwardedRef(withGlobalProps(TextArea, 'TextArea'));
165
+ export const TextAreaWithGlobalProps = withGlobalProps(TextArea, 'TextArea');
206
166
 
207
167
  export default TextAreaWithGlobalProps;
@@ -37,11 +37,11 @@
37
37
  }
38
38
 
39
39
  // Visual variants
40
- .rootVariantFilled {
40
+ .isRootVariantFilled {
41
41
  @include variants.visual(box, $variant: filled);
42
42
  }
43
43
 
44
- .rootVariantOutline {
44
+ .isRootVariantOutline {
45
45
  @include variants.visual(box, $variant: outline);
46
46
  }
47
47
 
@@ -64,12 +64,12 @@
64
64
  }
65
65
 
66
66
  // Layouts
67
- .rootLayoutVertical,
68
- .rootLayoutHorizontal {
67
+ .isRootLayoutVertical,
68
+ .isRootLayoutHorizontal {
69
69
  @include box-field-layout.vertical();
70
70
  }
71
71
 
72
- .rootLayoutHorizontal {
72
+ .isRootLayoutHorizontal {
73
73
  @include box-field-layout.horizontal();
74
74
  }
75
75
 
@@ -82,14 +82,14 @@
82
82
  }
83
83
 
84
84
  // Sizes
85
- .rootSizeSmall {
85
+ .isRootSizeSmall {
86
86
  @include box-field-sizes.size(small, $is-multiline: true);
87
87
  }
88
88
 
89
- .rootSizeMedium {
89
+ .isRootSizeMedium {
90
90
  @include box-field-sizes.size(medium, $is-multiline: true);
91
91
  }
92
92
 
93
- .rootSizeLarge {
93
+ .isRootSizeLarge {
94
94
  @include box-field-sizes.size(large, $is-multiline: true);
95
95
  }
@@ -1 +1 @@
1
- export { default } from './TextArea';
1
+ export { default as TextArea } from './TextArea';