superdesk-ui-framework 4.0.27 → 4.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/app-typescript/components/Alert.tsx +11 -1
  2. package/app-typescript/components/Button.tsx +47 -17
  3. package/app-typescript/components/FormLabel.tsx +7 -1
  4. package/app-typescript/components/Label.tsx +2 -13
  5. package/app-typescript/components/RadioButtonGroup.tsx +6 -5
  6. package/app-typescript/components/SelectPreview.tsx +1 -1
  7. package/app-typescript/components/ShowPopup.tsx +28 -19
  8. package/app-typescript/components/Tooltip.tsx +22 -6
  9. package/app-typescript/components/TreeSelect/TreeSelect.tsx +4 -21
  10. package/app-typescript/components/TreeSelect/TreeSelectItem.tsx +1 -1
  11. package/app-typescript/components/TreeSelect/TreeSelectPill.tsx +1 -1
  12. package/app-typescript/helpers.tsx +13 -0
  13. package/app-typescript/index.ts +1 -0
  14. package/dist/components/Buttons.tsx +6 -6
  15. package/dist/examples.bundle.js +37093 -37033
  16. package/dist/playgrounds/react-playgrounds/TestGround.tsx +1 -1
  17. package/dist/superdesk-ui.bundle.js +36975 -36916
  18. package/dist/vendor.bundle.js +7 -7
  19. package/examples/pages/components/Buttons.tsx +6 -6
  20. package/examples/pages/playgrounds/react-playgrounds/TestGround.tsx +1 -1
  21. package/package.json +1 -1
  22. package/react/components/Alert.d.ts +1 -0
  23. package/react/components/Alert.js +5 -1
  24. package/react/components/Button.d.ts +1 -0
  25. package/react/components/Button.js +35 -4
  26. package/react/components/FormLabel.d.ts +1 -0
  27. package/react/components/FormLabel.js +1 -1
  28. package/react/components/Label.d.ts +0 -1
  29. package/react/components/Label.js +3 -15
  30. package/react/components/RadioButtonGroup.d.ts +3 -2
  31. package/react/components/RadioButtonGroup.js +3 -3
  32. package/react/components/SelectPreview.js +3 -3
  33. package/react/components/ShowPopup.d.ts +1 -1
  34. package/react/components/ShowPopup.js +7 -7
  35. package/react/components/Tooltip.d.ts +9 -1
  36. package/react/components/Tooltip.js +40 -10
  37. package/react/components/TreeSelect/TreeSelect.js +5 -14
  38. package/react/components/TreeSelect/TreeSelectItem.js +2 -2
  39. package/react/components/TreeSelect/TreeSelectPill.js +3 -3
  40. package/react/helpers.d.ts +1 -0
  41. package/react/helpers.js +14 -1
  42. package/react/index.d.ts +1 -0
  43. package/react/index.js +3 -1
@@ -10,6 +10,7 @@ interface IProps {
10
10
  icon?: string;
11
11
  banner?: boolean;
12
12
  margin?: 'none' | 'small' | 'normal' | 'large';
13
+ fullWidth?: boolean;
13
14
  }
14
15
 
15
16
  interface IState {
@@ -47,8 +48,17 @@ export class Alert extends React.PureComponent<IProps, IState> {
47
48
  'sd-alert__info-btn--hidden': this.state.open,
48
49
  });
49
50
 
51
+ const styles: React.CSSProperties = {};
52
+
53
+ if (this.props.fullWidth) {
54
+ styles.width = '100%';
55
+ }
56
+
50
57
  return (
51
- <div className='sd-alert__container'>
58
+ <div
59
+ className='sd-alert__container'
60
+ style={styles}
61
+ >
52
62
  <div className={classesAlert}>
53
63
  {this.props.icon ?
54
64
  <span className="sd-alert__icon">
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import classNames from 'classnames';
3
- import { Icon } from './Icon';
4
- import { Spinner } from './Spinner';
3
+ import {Icon} from './Icon';
4
+ import {Spinner} from './Spinner';
5
+ import {WithTooltip} from './Tooltip';
5
6
 
6
7
  interface IPropsButton {
7
8
  text: string;
@@ -22,6 +23,7 @@ interface IPropsButton {
22
23
  icon?: string;
23
24
  disabled?: boolean;
24
25
  iconOnly?: boolean;
26
+ noMargin?: boolean;
25
27
  'data-test-id'?: string;
26
28
  }
27
29
 
@@ -41,21 +43,49 @@ export class Button extends React.PureComponent<IPropsButton> {
41
43
  });
42
44
 
43
45
  return (
44
- <button
45
- id={this.props.id}
46
- className={classes}
47
- tabIndex={0}
48
- disabled={this.props.disabled || this.props.isLoading}
49
- data-loading={this.props.isLoading}
50
- onClick={this.props.disabled ? () => false : (event) => this.props.onClick(event)}
51
- aria-label={this.props.iconOnly ? this.props.text : ''}
52
- data-test-id={this.props['data-test-id']}
53
- title={this.props.tooltip}
54
- >
55
- {this.props.isLoading ? <Spinner size="mini" /> : null}
56
- {this.props.icon && !this.props.isLoading ? <Icon ariaHidden name={this.props.icon} /> : null}
57
- {this.props.iconOnly ? null : this.props.text}
58
- </button>
46
+ <TooltipWrapper tooltipText={this.props.tooltip}>
47
+ {({attributes}) => (
48
+ <button
49
+ {...attributes}
50
+ id={this.props.id}
51
+ className={classes}
52
+ tabIndex={0}
53
+ disabled={this.props.disabled || this.props.isLoading}
54
+ data-loading={this.props.isLoading}
55
+ onClick={this.props.disabled ? () => false : (event) => this.props.onClick(event)}
56
+ aria-label={this.props.iconOnly ? this.props.text : ''}
57
+ data-test-id={this.props['data-test-id']}
58
+ style={this.props.noMargin ? {margin: 0} : undefined}
59
+ >
60
+ {this.props.isLoading ? <Spinner size="mini" /> : null}
61
+ {this.props.icon && !this.props.isLoading ? <Icon ariaHidden name={this.props.icon} /> : null}
62
+ {this.props.iconOnly ? null : this.props.text}
63
+ </button>
64
+ )}
65
+ </TooltipWrapper>
59
66
  );
60
67
  }
61
68
  }
69
+
70
+ interface ITooltipWrapperProps {
71
+ tooltipText: string | null | undefined;
72
+ children: React.ComponentProps<typeof WithTooltip>['children'];
73
+ }
74
+
75
+ class TooltipWrapper extends React.PureComponent<ITooltipWrapperProps> {
76
+ render() {
77
+ const {tooltipText, children} = this.props;
78
+
79
+ return (tooltipText ?? '').length > 0
80
+ ? (
81
+ <WithTooltip text={tooltipText}>
82
+ {({attributes}) => children({attributes})}
83
+ </WithTooltip>
84
+ )
85
+ : (
86
+ <>
87
+ {children({attributes: {}})}
88
+ </>
89
+ );
90
+ }
91
+ }
@@ -4,6 +4,7 @@ import classNames from 'classnames';
4
4
  interface IProps {
5
5
  text: string;
6
6
  style?: 'normal' | 'light'; // defaults to normal
7
+ noMinHeight?: boolean;
7
8
  }
8
9
 
9
10
  export class FormLabel extends React.PureComponent<IProps> {
@@ -14,7 +15,12 @@ export class FormLabel extends React.PureComponent<IProps> {
14
15
  });
15
16
 
16
17
  return (
17
- <label className={classes}>{this.props.text}</label>
18
+ <label
19
+ className={classes}
20
+ style={this.props.noMinHeight === true ? {minHeight: 'auto'} : undefined}
21
+ >
22
+ {this.props.text}
23
+ </label>
18
24
  );
19
25
  }
20
26
  }
@@ -1,5 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import classNames from 'classnames';
3
+ import {getTextColor} from '../helpers';
4
+
3
5
  interface IProps {
4
6
  text: string;
5
7
  link?: string;
@@ -77,16 +79,3 @@ export class Label extends React.PureComponent<IProps> {
77
79
  }
78
80
  }
79
81
  }
80
-
81
- export function getTextColor(backgroundColor: string): 'black' | 'white' | undefined {
82
- if (backgroundColor) {
83
- const r = parseInt(backgroundColor.substr(1, 2), 16);
84
- const g = parseInt(backgroundColor.substr(3, 2), 16);
85
- const b = parseInt(backgroundColor.substr(5, 2), 16);
86
- const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
87
-
88
- return (yiq >= 128) ? 'black' : 'white';
89
- } else {
90
- return;
91
- }
92
- }
@@ -4,7 +4,9 @@ import nextId from "react-id-generator";
4
4
  import {FormLabel} from './Form/FormLabel';
5
5
 
6
6
  interface IProps {
7
- value?: string;
7
+ value: string;
8
+ onChange(nextValue: string): void;
9
+ disabled?: boolean;
8
10
  group?: {
9
11
  orientation?: 'horizontal' | 'vertical'; // defaults to 'horizontal'
10
12
  grid?: boolean;
@@ -22,7 +24,6 @@ interface IProps {
22
24
  }>;
23
25
  required?: boolean;
24
26
  tabindex?: number;
25
- onChange(nextValue: string): void;
26
27
  'data-test-id'?: string;
27
28
  }
28
29
 
@@ -35,7 +36,7 @@ export class RadioButtonGroup extends React.Component<IProps> {
35
36
  }
36
37
 
37
38
  handleChange(item: any) {
38
- if (!item.disabled) {
39
+ if (this.props.disabled !== true && item.disabled !== true) {
39
40
  this.props.onChange(item.value);
40
41
  }
41
42
  }
@@ -73,7 +74,7 @@ export class RadioButtonGroup extends React.Component<IProps> {
73
74
  tabIndex={this.props.tabindex}
74
75
  name={this.htmlId}
75
76
  onChange={() => this.handleChange(item)}
76
- disabled={item.disabled}
77
+ disabled={this.props.disabled || item.disabled}
77
78
  required={this.props.required}
78
79
  checked={item.value === this.props.value} />
79
80
  <label
@@ -110,7 +111,7 @@ export class RadioButtonGroup extends React.Component<IProps> {
110
111
  tabIndex={0}
111
112
  name={this.htmlId}
112
113
  onChange={() => this.handleChange(item)}
113
- disabled={item.disabled}
114
+ disabled={this.props.disabled || item.disabled}
114
115
  required={this.props.required}
115
116
  checked={item.value === this.props.value} />
116
117
  <label className="sd-check-button__text-label" htmlFor={this.htmlId + index}
@@ -1,6 +1,6 @@
1
1
  import classNames from 'classnames';
2
2
  import * as React from 'react';
3
- import {getTextColor} from './Label';
3
+ import {getTextColor} from '../helpers';
4
4
 
5
5
  interface IProps<T> {
6
6
  items: Array<T>;
@@ -7,7 +7,7 @@ import maxSize from 'popper-max-size-modifier';
7
7
  import {getNextZIndex} from '../zIndex';
8
8
 
9
9
  interface IPropsPopupPositioner {
10
- referenceElement: HTMLElement;
10
+ getReferenceElement(): HTMLElement;
11
11
  placement: Placement;
12
12
  onClose(): void;
13
13
  closeOnHoverEnd?: boolean;
@@ -34,7 +34,7 @@ export class PopupPositioner extends React.PureComponent<IPropsPopupPositioner>
34
34
  }
35
35
 
36
36
  if (
37
- this.props.referenceElement.contains(event.target as Node) !== true
37
+ this.props.getReferenceElement().contains(event.target as Node) !== true
38
38
  && this.wrapperEl.contains(event.target as Node) !== true
39
39
  ) {
40
40
  this.props.onClose();
@@ -66,7 +66,7 @@ export class PopupPositioner extends React.PureComponent<IPropsPopupPositioner>
66
66
  window.addEventListener('scroll', this.closeOnScroll, true);
67
67
 
68
68
  if (this.props.closeOnHoverEnd && this.wrapperEl != null) {
69
- this.props.referenceElement.addEventListener('mouseleave', this.closeOnMouseLeave);
69
+ this.props.getReferenceElement().addEventListener('mouseleave', this.closeOnMouseLeave);
70
70
  this.wrapperEl.addEventListener('mouseleave', this.closeOnMouseLeave);
71
71
  }
72
72
 
@@ -91,7 +91,7 @@ export class PopupPositioner extends React.PureComponent<IPropsPopupPositioner>
91
91
  setTimeout(() => {
92
92
  if (this.wrapperEl != null) {
93
93
  this.popper = createPopper(
94
- this.props.referenceElement,
94
+ this.props.getReferenceElement(),
95
95
  this.wrapperEl,
96
96
  {
97
97
  placement: this.props.placement,
@@ -111,7 +111,7 @@ export class PopupPositioner extends React.PureComponent<IPropsPopupPositioner>
111
111
  window.removeEventListener('scroll', this.closeOnScroll, true);
112
112
 
113
113
  if (this.props.closeOnHoverEnd && this.wrapperEl != null) {
114
- this.props.referenceElement.removeEventListener('mouseleave', this.closeOnMouseLeave);
114
+ this.props.getReferenceElement().removeEventListener('mouseleave', this.closeOnMouseLeave);
115
115
  this.wrapperEl.removeEventListener('mouseleave', this.closeOnMouseLeave);
116
116
  }
117
117
 
@@ -120,19 +120,28 @@ export class PopupPositioner extends React.PureComponent<IPropsPopupPositioner>
120
120
 
121
121
  render() {
122
122
  return (
123
- <div
124
- ref={(el) => {
125
- this.wrapperEl = el;
126
- }}
127
- style={{
128
- position: 'absolute',
129
- left: '-100vw',
130
- display: 'flex',
131
- zIndex: this.zIndex,
132
- }}
133
- >
134
- {this.props.children}
135
- </div>
123
+ <>
124
+ {
125
+ ReactDOM.createPortal(
126
+ (
127
+ <div
128
+ ref={(el) => {
129
+ this.wrapperEl = el;
130
+ }}
131
+ style={{
132
+ position: 'absolute',
133
+ left: '-100vw',
134
+ display: 'flex',
135
+ zIndex: this.zIndex,
136
+ }}
137
+ >
138
+ {this.props.children}
139
+ </div>
140
+ ),
141
+ document.body,
142
+ )
143
+ }
144
+ </>
136
145
  );
137
146
  }
138
147
  }
@@ -160,7 +169,7 @@ export function showPopup(
160
169
  ReactDOM.render(
161
170
  (
162
171
  <PopupPositioner
163
- referenceElement={referenceElement}
172
+ getReferenceElement={() => referenceElement}
164
173
  placement={placement}
165
174
  onClose={closeFn}
166
175
  closeOnHoverEnd={closeOnHoverEnd || false}
@@ -1,10 +1,12 @@
1
1
  import * as React from 'react';
2
+ import nextId from "react-id-generator";
2
3
  import tippy, {Instance, Placement} from 'tippy.js';
3
4
  import {assertNever} from '../helpers';
4
5
 
5
6
  interface IProps {
6
7
  text: string | undefined | null;
7
8
  flow?: 'top' | 'left' | 'right' | 'down'; // defaults to 'top'
9
+ children(options: {attributes: {[name: string]: string}}): React.ReactNode;
8
10
  }
9
11
 
10
12
  function flowToPlacement(flow: IProps['flow']): Placement | undefined {
@@ -24,14 +26,18 @@ function flowToPlacement(flow: IProps['flow']): Placement | undefined {
24
26
  }
25
27
  }
26
28
 
27
- export class Tooltip extends React.PureComponent<IProps> {
29
+ const tooltipAttributeName = 'data-with-tooltip';
30
+ const getTooltipSelector = (value: string) => `[${tooltipAttributeName}=${value}]`;
31
+
32
+ export class WithTooltip extends React.PureComponent<IProps> {
28
33
  private id: string;
29
34
  private instance: Instance | null;
30
35
 
31
36
  constructor(props: IProps) {
32
37
  super(props);
33
38
 
34
- this.id = 'tooltip-' + Math.random().toString().slice(2);
39
+ this.id = nextId();
40
+
35
41
  this.instance = null;
36
42
  }
37
43
 
@@ -40,7 +46,7 @@ export class Tooltip extends React.PureComponent<IProps> {
40
46
  const content = this.props.text;
41
47
 
42
48
  if (this.instance == null) {
43
- this.instance = tippy('#' + this.id, {
49
+ this.instance = tippy(getTooltipSelector(this.id), {
44
50
  placement: placement,
45
51
  })[0];
46
52
 
@@ -82,11 +88,21 @@ export class Tooltip extends React.PureComponent<IProps> {
82
88
  this.setupTooltip();
83
89
  }
84
90
 
91
+ render() {
92
+ return this.props.children({attributes: {[tooltipAttributeName]: this.id}});
93
+ }
94
+ }
95
+
96
+ export class Tooltip extends React.PureComponent<Omit<IProps, 'children'>> {
85
97
  render() {
86
98
  return (
87
- <div id={this.id} style={{display: 'inline-flex'}}>
88
- {this.props.children}
89
- </div>
99
+ <WithTooltip text={this.props.text} flow={this.props.flow}>
100
+ {({attributes}) => (
101
+ <div {...attributes} style={{display: 'inline-flex'}}>
102
+ {this.props.children}
103
+ </div>
104
+ )}
105
+ </WithTooltip>
90
106
  );
91
107
  }
92
108
  }
@@ -6,7 +6,7 @@ import _debounce from 'lodash/debounce';
6
6
  import { InputWrapper } from "../Form";
7
7
  import { createPopper, Instance } from '@popperjs/core';
8
8
  import {isEqual} from 'lodash';
9
- import {getTextColor} from '../Label';
9
+ import {getTextColor} from '../../helpers';
10
10
  import {IInputWrapper} from '../Form/InputWrapper';
11
11
  import {SelectPreview} from '../SelectPreview';
12
12
  import {TreeSelectPill} from './TreeSelectPill';
@@ -15,14 +15,7 @@ import {keyboardNavigation} from './KeyboardNavigation';
15
15
  import {WithPortal} from '../WithPortal';
16
16
  import { DragDropContext, Droppable, Draggable, DropResult } from "react-beautiful-dnd";
17
17
  import {getNextZIndex} from '../../zIndex';
18
-
19
- const reorder = (list: Array<any>, startIndex: number, endIndex: number) => {
20
- const result = Array.from(list);
21
- const [removed] = result.splice(startIndex, 1);
22
- result.splice(endIndex, 0, removed);
23
-
24
- return result;
25
- };
18
+ import {arrayMove} from '@superdesk/common';
26
19
 
27
20
  interface IState<T> {
28
21
  value: Array<T>;
@@ -282,14 +275,9 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
282
275
  }
283
276
 
284
277
  removeClick(i: number) {
285
- let newTags = this.state.value;
286
- newTags?.splice(i, 1);
287
-
288
278
  this.setState({
289
- value: newTags,
279
+ value: this.state.value.filter((_item, index) => index !== i),
290
280
  });
291
-
292
- this.props.onChange(this.state.value);
293
281
  }
294
282
 
295
283
  handleMultiLevel(item: ITreeNode<T>) {
@@ -639,13 +627,8 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
639
627
  return;
640
628
  }
641
629
 
642
- const value = reorder(
643
- this.state.value,
644
- result.source.index,
645
- result.destination.index,
646
- );
647
630
  this.setState({
648
- value: value,
631
+ value: arrayMove(this.state.value, result.source.index, result.destination.index),
649
632
  });
650
633
  }
651
634
 
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Icon } from "../Icon";
3
- import {getTextColor} from '../Label';
3
+ import {getTextColor} from '../../helpers';
4
4
  import {ITreeNode} from './TreeSelect';
5
5
 
6
6
  export function getPrefixedItemId(id: string) {
@@ -2,7 +2,7 @@ import classNames from 'classnames';
2
2
  import * as React from "react";
3
3
  import {DragHandle} from '../DragHandle';
4
4
  import {Icon} from "../Icon";
5
- import {getTextColor} from '../Label';
5
+ import {getTextColor} from '../../helpers';
6
6
 
7
7
  interface IProps<T> {
8
8
  item: T;
@@ -5,3 +5,16 @@ export function assertNever(x: never): never {
5
5
  export function nameof<T>(name: keyof T): string {
6
6
  return name.toString();
7
7
  }
8
+
9
+ export function getTextColor(backgroundColor: string): 'black' | 'white' | undefined {
10
+ if (backgroundColor) {
11
+ const r = parseInt(backgroundColor.substr(1, 2), 16);
12
+ const g = parseInt(backgroundColor.substr(3, 2), 16);
13
+ const b = parseInt(backgroundColor.substr(5, 2), 16);
14
+ const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
15
+
16
+ return (yiq >= 128) ? 'black' : 'white';
17
+ } else {
18
+ return;
19
+ }
20
+ }
@@ -107,6 +107,7 @@ export { ResizeObserverComponent } from './components/ResizeObserverComponent';
107
107
  export { DragHandleDots } from './components/DragHandleDots';
108
108
  export { DragHandle } from './components/DragHandle';
109
109
  export { CalendarWeekDayItem } from './components/Lists/CalendarWeekDayItem';
110
+ export { getTextColor } from './helpers';
110
111
 
111
112
  // declare non-typescript exports to prevent errors
112
113
  export declare const ToggleBoxNext: any;
@@ -17,7 +17,7 @@ export default class ButtonsDoc extends React.Component {
17
17
  <Markup.ReactMarkup>
18
18
  <Markup.ReactMarkupPreview>
19
19
  <div className="docs-page__content-row">
20
- <Button text="default" onClick={()=> false} />
20
+ <Button text="default" onClick={()=> false} tooltip="test tooltip" />
21
21
  <Button text="primary" type="primary" onClick={()=> false} />
22
22
  </div>
23
23
  <p className="docs-page__paragraph">// Other colour options</p>
@@ -101,8 +101,8 @@ export default class ButtonsDoc extends React.Component {
101
101
 
102
102
  <h3 className="docs-page__h3">Sizing</h3>
103
103
  <p className="docs-page__paragraph">
104
- For the default button, no size has to be specified.
105
- To change the default size set the <code>size</code> value either to <code>small</code> or <code>large</code>.
104
+ For the default button, no size has to be specified.
105
+ To change the default size set the <code>size</code> value either to <code>small</code> or <code>large</code>.
106
106
  For the button to take the full width of the container add <code>expand={'{true}'}</code>.
107
107
  </p>
108
108
  <Markup.ReactMarkup>
@@ -120,7 +120,7 @@ export default class ButtonsDoc extends React.Component {
120
120
  </div>
121
121
  <div className="docs-page__content-row">
122
122
  <Button text="small expanded button" expand={true} size="small" onClick={()=> false} />
123
- </div>
123
+ </div>
124
124
  </Markup.ReactMarkupPreview>
125
125
  <Markup.ReactMarkupCode>{`
126
126
  <Button text="button large" size="large" onClick={()=> false} />
@@ -201,7 +201,7 @@ export default class ButtonsDoc extends React.Component {
201
201
  <Button text="success" type="success" icon="ok" onClick={()=> false} />
202
202
  <Button text="warning" type="warning" icon="exclamation-sign" onClick={()=> false} />
203
203
  <Button text="alert" type="alert" icon="warning-sign" onClick={()=> false} />
204
-
204
+
205
205
  <Button text="default" icon="info-sign" style="hollow" onClick={()=> false} />
206
206
  <Button text="primary" type="primary" icon="plus-sign" style="hollow" onClick={()=> false} />
207
207
  <Button text="success" type="success" icon="ok" style="hollow" onClick={()=> false} />
@@ -217,7 +217,7 @@ export default class ButtonsDoc extends React.Component {
217
217
  </Markup.ReactMarkup>
218
218
 
219
219
  <h3 className="docs-page__h3">Buttons with icon font only</h3>
220
- <p className="docs-page__paragraph">Buttons can also contain only an icon, without any visible text. To achieve this specify the <code>icon</code> value and set <code>iconOnly={true}</code>.
220
+ <p className="docs-page__paragraph">Buttons can also contain only an icon, without any visible text. To achieve this specify the <code>icon</code> value and set <code>iconOnly={true}</code>.
221
221
  The specified text value will be used for the <code>aria-label</code>.</p>
222
222
  <Markup.ReactMarkup>
223
223
  <Markup.ReactMarkupPreview>