@splunk/react-ui 5.7.1 → 5.9.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.
Files changed (152) hide show
  1. package/Accordion.js +6 -6
  2. package/Anchor.js +2 -1
  3. package/Box.js +83 -34
  4. package/CHANGELOG.md +51 -0
  5. package/Calendar.js +134 -134
  6. package/Clickable.js +131 -94
  7. package/CollapsiblePanel.js +175 -137
  8. package/ComboBox.js +32 -27
  9. package/ControlGroup.js +92 -91
  10. package/DefinitionList.js +9 -9
  11. package/Drawer.d.ts +2 -0
  12. package/Drawer.js +679 -0
  13. package/Dropdown.js +27 -18
  14. package/DualListbox.js +1 -1
  15. package/File.js +35 -35
  16. package/JSONTree.js +73 -72
  17. package/Link.js +2 -2
  18. package/MIGRATION.md +10 -0
  19. package/Menu.js +403 -261
  20. package/Modal.js +263 -252
  21. package/Monogram.js +2 -2
  22. package/Multiselect.js +551 -385
  23. package/Number.js +2 -1
  24. package/Paginator.js +14 -12
  25. package/Popover.js +4 -1
  26. package/README.md +11 -0
  27. package/RadioBar.js +1 -1
  28. package/Search.js +111 -95
  29. package/Select.js +42 -40
  30. package/SelectBase.js +819 -715
  31. package/SidePanel.js +346 -167
  32. package/SlidingPanels.js +11 -11
  33. package/StepBar.js +7 -7
  34. package/Switch.js +5 -5
  35. package/Table.js +116 -119
  36. package/Text.js +48 -48
  37. package/TextArea.js +7 -7
  38. package/TransitionOpen.js +188 -169
  39. package/docs-llm/Accordion.md +267 -0
  40. package/docs-llm/Anchor Menu.md +115 -0
  41. package/docs-llm/Anchor.md +54 -0
  42. package/docs-llm/AnimationToggle.md +254 -0
  43. package/docs-llm/Avatar.md +292 -0
  44. package/docs-llm/Badge.md +212 -0
  45. package/docs-llm/Breadcrumbs.md +306 -0
  46. package/docs-llm/Button Group.md +53 -0
  47. package/docs-llm/Button.md +361 -0
  48. package/docs-llm/Card Layout.md +286 -0
  49. package/docs-llm/Card.md +619 -0
  50. package/docs-llm/Checkbox.md +218 -0
  51. package/docs-llm/Chip.md +291 -0
  52. package/docs-llm/Clickable.md +160 -0
  53. package/docs-llm/Code.md +292 -0
  54. package/docs-llm/Collapsible Panel.md +744 -0
  55. package/docs-llm/Color.md +253 -0
  56. package/docs-llm/Column Layout.md +391 -0
  57. package/docs-llm/Combo Box.md +540 -0
  58. package/docs-llm/Control Group.md +594 -0
  59. package/docs-llm/Date.md +270 -0
  60. package/docs-llm/Definition List.md +278 -0
  61. package/docs-llm/Divider.md +216 -0
  62. package/docs-llm/Drawer.md +414 -0
  63. package/docs-llm/Dropdown.md +472 -0
  64. package/docs-llm/Dual Listbox.md +325 -0
  65. package/docs-llm/File.md +653 -0
  66. package/docs-llm/Form Rows.md +374 -0
  67. package/docs-llm/Heading.md +179 -0
  68. package/docs-llm/Image.md +109 -0
  69. package/docs-llm/JSON Tree.md +260 -0
  70. package/docs-llm/Layer.md +74 -0
  71. package/docs-llm/Layout.md +50 -0
  72. package/docs-llm/Link.md +318 -0
  73. package/docs-llm/List.md +189 -0
  74. package/docs-llm/Markdown.md +179 -0
  75. package/docs-llm/Menu.md +735 -0
  76. package/docs-llm/Message Bar.md +236 -0
  77. package/docs-llm/Message.md +248 -0
  78. package/docs-llm/Modal.md +443 -0
  79. package/docs-llm/Monogram.md +159 -0
  80. package/docs-llm/Multiselect.md +939 -0
  81. package/docs-llm/Notifications.md +46 -0
  82. package/docs-llm/Number.md +298 -0
  83. package/docs-llm/Paginator.md +395 -0
  84. package/docs-llm/Paragraph.md +148 -0
  85. package/docs-llm/Phone Number.md +254 -0
  86. package/docs-llm/Popover.md +166 -0
  87. package/docs-llm/Progress.md +141 -0
  88. package/docs-llm/Radio Bar.md +303 -0
  89. package/docs-llm/Radio List.md +350 -0
  90. package/docs-llm/Resize.md +362 -0
  91. package/docs-llm/Screen Reader Content.md +73 -0
  92. package/docs-llm/Scroll Container Context.md +155 -0
  93. package/docs-llm/Scroll.md +152 -0
  94. package/docs-llm/Search.md +381 -0
  95. package/docs-llm/Select.md +985 -0
  96. package/docs-llm/Side Panel.md +777 -0
  97. package/docs-llm/Slider.md +339 -0
  98. package/docs-llm/Sliding Panels.md +340 -0
  99. package/docs-llm/Split Button.md +295 -0
  100. package/docs-llm/Static Content.md +90 -0
  101. package/docs-llm/Step Bar.md +292 -0
  102. package/docs-llm/Switch.md +268 -0
  103. package/docs-llm/Tab Bar.md +439 -0
  104. package/docs-llm/Tab Layout.md +398 -0
  105. package/docs-llm/Table.md +2642 -0
  106. package/docs-llm/Text Area.md +253 -0
  107. package/docs-llm/Text.md +339 -0
  108. package/docs-llm/Tooltip.md +325 -0
  109. package/docs-llm/Transition Open.md +406 -0
  110. package/docs-llm/Tree.md +591 -0
  111. package/docs-llm/Typography.md +125 -0
  112. package/docs-llm/Wait Spinner.md +121 -0
  113. package/docs-llm/llms.txt +101 -0
  114. package/package.json +6 -5
  115. package/types/src/Box/Box.d.ts +2 -10
  116. package/types/src/Drawer/Body.d.ts +17 -0
  117. package/types/src/Drawer/Drawer.d.ts +114 -0
  118. package/types/src/Drawer/DrawerContext.d.ts +11 -0
  119. package/types/src/Drawer/Footer.d.ts +25 -0
  120. package/types/src/Drawer/Header.d.ts +41 -0
  121. package/types/src/Drawer/docs/examples/Basic.d.ts +6 -0
  122. package/types/src/Drawer/docs/examples/ContainerPosition.d.ts +7 -0
  123. package/types/src/Drawer/docs/examples/InitialFocus.d.ts +9 -0
  124. package/types/src/Drawer/docs/examples/InlinePosition.d.ts +7 -0
  125. package/types/src/Drawer/docs/examples/PagePosition.d.ts +7 -0
  126. package/types/src/Drawer/index.d.ts +2 -0
  127. package/types/src/JSONTree/JSONTree.d.ts +12 -5
  128. package/types/src/JSONTree/renderTreeItems.d.ts +2 -1
  129. package/types/src/Menu/Item.d.ts +2 -1
  130. package/types/src/Menu/docs/examples/SelectableCheckbox.d.ts +7 -0
  131. package/types/src/Modal/Modal.d.ts +1 -2
  132. package/types/src/Multiselect/Compact.d.ts +8 -3
  133. package/types/src/Multiselect/Multiselect.d.ts +8 -3
  134. package/types/src/Multiselect/Normal.d.ts +8 -3
  135. package/types/src/Multiselect/Option.d.ts +6 -3
  136. package/types/src/Multiselect/docs/examples/Disabled.d.ts +1 -0
  137. package/types/src/Select/Option.d.ts +6 -3
  138. package/types/src/Select/Select.d.ts +8 -5
  139. package/types/src/Select/docs/examples/Dimmed.d.ts +7 -0
  140. package/types/src/SelectBase/OptionBase.d.ts +6 -3
  141. package/types/src/SelectBase/SelectBase.d.ts +8 -3
  142. package/types/src/SidePanel/SidePanel.d.ts +43 -2
  143. package/types/src/SidePanel/docs/examples/DockLayout.d.ts +17 -0
  144. package/types/src/SidePanel/docs/examples/InitialFocus.d.ts +9 -0
  145. package/types/src/TransitionOpen/TransitionOpen.d.ts +29 -4
  146. package/types/src/useKeyPress/index.d.ts +9 -2
  147. package/types/src/useOnClickOutside/index.d.ts +2 -0
  148. package/types/src/useOnClickOutside/useOnClickOutside.d.ts +4 -0
  149. package/useKeyPress.js +23 -18
  150. package/useOnClickOutside.d.ts +2 -0
  151. package/useOnClickOutside.js +79 -0
  152. package/types/src/RadioList/docs/examples/Row.d.ts +0 -6
@@ -0,0 +1,339 @@
1
+ # Slider
2
+
3
+ ## Overview
4
+
5
+
6
+ > Image: Illustration of a Slider component
7
+
8
+
9
+
10
+ ## When to use this component
11
+ - To choose a single number within a range with minimum and maximum values
12
+
13
+
14
+ ## When to use another component
15
+ - For precise number input where a range is not defined, consider `Number`
16
+ - For an input that is from a non-continuous range, consider `Select`
17
+
18
+ ```mermaid
19
+ graph TD
20
+ accDescr: Decision tree that guides on when to use the Slider component or something else
21
+ A(Is there a defined continuous range with min and max values?) -- Yes --- B(Slider)
22
+ A -- No --- C(Is the input from a small, non-continuous range?)
23
+ C -- Yes --- D(Select)
24
+ C -- No --- E(Number)
25
+ ```
26
+
27
+ ### Check out
28
+ - [Number][1]
29
+ - [Select][2]
30
+
31
+ ## Behaviors
32
+ ### Controlled slider
33
+ If the slider use case requires more precision, use the slider along with the Number component. <br />
34
+ [View controlled Slider example](Slider?section=examples#Controlled)
35
+
36
+ ### Step marks
37
+ Sliders with step marks allows users to choose from discrete values. The thumb will snap to the ticks. <br />
38
+ [View Slider with step marks example](Slider?section=examples#Step%20marks)
39
+
40
+ ## Usage
41
+ ### Use descriptive text for custom labels
42
+ Sliders support adding custom labels for the range. Keep these succinct and descriptive so that the user knows what the range is depicting.
43
+
44
+ > Image: The image illustrates two examples of a volume control slider. In the good example, the slider is labeled with descriptive text, showing
45
+
46
+
47
+ ### Avoid selecting ranges instead of values
48
+ Sliders do not support selecting a subset range within the range. Currently, the slider thumb can only select a single value.
49
+
50
+ > Image: The image illustrates two examples of a volume control slider. In the good example, the slider only has one thumb, selecting an exact value. In the bad example, the slider has two thumbs, selecting a subset of a range in the slider.
51
+
52
+
53
+
54
+ ## Content guidelines
55
+
56
+ ### Use parallel terminology
57
+ Slider labels should briefly describe what the range represents. Define the values at the min and max of the range. For non-numerical ranges, use parallel terminology, like min/max and high/low.
58
+
59
+ > Image: The image illustrates two examples of a volume control slider with different value labels. In the good example, the slider labels uses parallel terminology of min and max, while the bad example shows the slider labels going from 0 to max.
60
+
61
+
62
+ [1]: ./Number
63
+ [2]: ./Select
64
+
65
+
66
+ ## Examples
67
+
68
+
69
+ ### Uncontrolled
70
+
71
+ ```typescript
72
+ import React from 'react';
73
+
74
+ import Slider from '@splunk/react-ui/Slider';
75
+
76
+
77
+ function Basic() {
78
+ return <Slider min={100} max={500} step={25} defaultValue={300} />;
79
+ }
80
+
81
+ export default Basic;
82
+ ```
83
+
84
+
85
+
86
+ ### Controlled
87
+
88
+ Slider syncing with a Number input.
89
+
90
+ ```typescript
91
+ import React, { Component } from 'react';
92
+
93
+ import ControlGroup from '@splunk/react-ui/ControlGroup';
94
+ import Number, { NumberChangeHandler } from '@splunk/react-ui/Number';
95
+ import Slider, { SliderChangeHandler } from '@splunk/react-ui/Slider';
96
+
97
+
98
+ class Controlled extends Component<object, { value?: number }> {
99
+ constructor(props: object) {
100
+ super(props);
101
+ this.state = { value: 300 };
102
+ }
103
+
104
+ handleSliderChange: SliderChangeHandler = (e, { value }) => {
105
+ this.setState({ value });
106
+ };
107
+
108
+ handleNumberChange: NumberChangeHandler = (e, { value }) => {
109
+ this.setState({ value });
110
+ };
111
+
112
+ render() {
113
+ return (
114
+ <ControlGroup label="Controls">
115
+ <Slider
116
+ inline
117
+ min={100}
118
+ max={500}
119
+ step={25}
120
+ onChange={this.handleSliderChange}
121
+ value={this.state.value}
122
+ />
123
+ <Number
124
+ inline
125
+ min={100}
126
+ max={500}
127
+ step={25}
128
+ value={this.state.value}
129
+ onChange={this.handleNumberChange}
130
+ style={{ flexBasis: 40 }}
131
+ />
132
+ </ControlGroup>
133
+ );
134
+ }
135
+ }
136
+
137
+ export default Controlled;
138
+ ```
139
+
140
+
141
+
142
+ ### Custom Labels
143
+
144
+ Labels can be modified or removed. Replacing all labels can create very different experiences, such as exponentially increasing values or ordered values (words only).
145
+
146
+ ```typescript
147
+ import React, { Component } from 'react';
148
+
149
+ import Slider, { SliderChangeHandler } from '@splunk/react-ui/Slider';
150
+
151
+
152
+ class CustomLabels extends Component<object, { displayValue: string; value: number }> {
153
+ static convertValueToLabel(value: number) {
154
+ const trueValue = 10 ** value;
155
+ const trueValueRounded = Math.round(trueValue * 100) / 100;
156
+
157
+ return `${trueValueRounded}px`;
158
+ }
159
+
160
+ constructor(props: object) {
161
+ super(props);
162
+ this.state = {
163
+ displayValue: CustomLabels.convertValueToLabel(1),
164
+ value: 1,
165
+ };
166
+ }
167
+
168
+ handleChange: SliderChangeHandler = (e, { value }) => {
169
+ this.setState({
170
+ displayValue: CustomLabels.convertValueToLabel(value),
171
+ value,
172
+ });
173
+ };
174
+
175
+ render() {
176
+ return (
177
+ <Slider
178
+ inline
179
+ displayValue={this.state.displayValue}
180
+ min={0}
181
+ minLabel="sharp"
182
+ max={2}
183
+ maxLabel="blurry"
184
+ step={0.2}
185
+ onChange={this.handleChange}
186
+ value={this.state.value}
187
+ />
188
+ );
189
+ }
190
+ }
191
+
192
+ export default CustomLabels;
193
+ ```
194
+
195
+
196
+
197
+ ### Disabled
198
+
199
+ ```typescript
200
+ import React from 'react';
201
+
202
+ import Slider from '@splunk/react-ui/Slider';
203
+
204
+
205
+ function Disabled() {
206
+ return <Slider min={1} max={100} step={1} defaultValue={50} inline disabled />;
207
+ }
208
+
209
+ export default Disabled;
210
+ ```
211
+
212
+
213
+
214
+ ### Step Marks
215
+
216
+ stepMarks can be set to always or never. Defaults to show on focus.
217
+
218
+ ```typescript
219
+ import React from 'react';
220
+
221
+ import Slider from '@splunk/react-ui/Slider';
222
+
223
+
224
+ function StepMarks() {
225
+ return (
226
+ <span>
227
+ <Slider min={100} max={200} step={10} defaultValue={150} stepMarks="always" inline />
228
+ <br />
229
+ <Slider min={100} max={200} step={10} defaultValue={150} stepMarks="never" inline />
230
+ </span>
231
+ );
232
+ }
233
+
234
+ export default StepMarks;
235
+ ```
236
+
237
+
238
+
239
+ ### Error
240
+
241
+ ```typescript
242
+ import React from 'react';
243
+
244
+ import Slider from '@splunk/react-ui/Slider';
245
+
246
+
247
+ function Error() {
248
+ return <Slider min={100} max={500} step={25} defaultValue={300} error />;
249
+ }
250
+
251
+ export default Error;
252
+ ```
253
+
254
+
255
+
256
+
257
+ ## API
258
+
259
+
260
+ ### Slider API
261
+
262
+ #### Props
263
+
264
+ | Name | Type | Required | Default | Description |
265
+ |------|------|------|------|------|
266
+ | defaultValue | number | no | | Set this property instead of value to make value uncontrolled. |
267
+ | describedBy | string | no | | The id of the description. When placed in a ControlGroup, this is automatically set to the ControlGroup's help component. |
268
+ | disabled | boolean | no | | Determines whether or not the slider can be moved. |
269
+ | displayValue | string | no | | The label shown in the tooltip. Defaults to the value. |
270
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
271
+ | error | boolean | no | | Highlight the Slider as having an error. The thumb and bar background-color turn to accent negative. |
272
+ | inline | boolean | no | | When false, display as inline-block with the default width. |
273
+ | inputId | string | no | | An id for the input, which may be necessary for accessibility, such as for aria attributes. |
274
+ | labelledBy | string | no | | The id of the label. When placed in a ControlGroup, this is automatically set to the ControlGroup's label. |
275
+ | max | number | no | 5 | The maximum value of the Slider input. |
276
+ | maxLabel | React.ReactNode | no | | The label shown to the right of the slider. Defaults to the max value. Set to null to remove. |
277
+ | min | number | no | 1 | The minimum value of the Slider input. |
278
+ | minLabel | React.ReactNode | no | | The label shown to the left of the slider. Defaults to the min value. Set to null to remove. |
279
+ | name | string | no | | The name is returned with onChange events, which can be used to identify the control when multiple controls share an onChange callback. |
280
+ | onChange | SliderChangeHandler | no | | Return event and data object with slider value. |
281
+ | step | number | no | 1 | The step value of the Slider input. |
282
+ | stepMarks | 'focus' \| 'always' \| 'never' | no | 'focus' | Determines whether or not the step marks should be shown. Defaults to show on focus. |
283
+ | thumbRef | React.Ref<HTMLButtonElement> | no | | A React ref which is set to the slider thumb when the component mounts and null when it unmounts. |
284
+ | value | number | no | | The value of the slider. Setting this value makes the property controlled. An `onChange` callback is required. |
285
+
286
+ #### Types
287
+
288
+ | Name | Type | Description |
289
+ |------|------|------|
290
+ | SliderChangeHandler | ( event: React.MouseEvent<HTMLDivElement> \| React.KeyboardEvent<HTMLButtonElement> \| MouseEvent, data: { name?: string; value: number; } ) => void | |
291
+
292
+
293
+
294
+
295
+
296
+ ## Accessibility
297
+
298
+ > NOT supported by design system: multiple thumbs
299
+
300
+ ## Visual Design
301
+ - Color contrast ratio **MUST** be:
302
+ - &gt=4.5:1 [SC 1.4.3][1]
303
+ - Any text to page-background (endpoints, tooltip text)
304
+ - &gt=3:1 for [SC 1.4.11][2]
305
+ - Selected color to page-background
306
+ - Unselected color to page-background
307
+ - Thumb to page-background
308
+ - Focus State: if the focus ring has a radius of [SC 1.4.11][2]
309
+ - &lt 3px: &gt=4.5.1 between thumb &lt&gt focus &lt&gt background
310
+ - &gt 3px: &gt=3.1 between thumb &lt&gt focus &lt&gt background
311
+
312
+ ## States
313
+ - Color contrast does not apply to disabled slider
314
+
315
+ ## Interaction Model
316
+ - In the case where two inputs are controlling a single value, such as a slider and number input,
317
+ focus **MUST** be on number input to change the value, as it has an easier interaction model on a keyboard than slider.
318
+ - Focus visible **MUST** be visible on thumb [SC 2.4.7][3]
319
+ - **MUST** have keyboard navigation [SC 2.1][4]
320
+ - <kbd>Tab</kbd> and <kbd>Shift+Tab</kbd>: focus lands on thumb
321
+ - <kbd>Left/Right Arrow</kbd>: moves thumb one step up or down
322
+ - <kbd>Up/Down</kbd>: moves thumb one step up or down
323
+ - <kbd>Home</kbd>: sets the thumb to the first allowed value in its range
324
+ - <kbd>End</kbd>: sets the thumb to the last allowed value in its range
325
+
326
+ ## Implementation
327
+ - Implementation **MUST** use either `aria-role="slider"` or HTML `input` with type `range`
328
+ - Slider element **MUST** have the following attributes based on its respective implementation:
329
+ - `aria-valuenow/value` set to a decimal value representing the current value of the slider
330
+ - `aria-valuemin/min` set to a decimal value representing the minimun allowed value of the slider
331
+ - `aria-valuemax/max` set to a decimal value representing the maximum allowed value of the slider
332
+ - For vertical slider, `aria-orientation` **MUST** be set to `vertical`. The default value of `aria-orientation` for slider is `horizontal`.
333
+
334
+ [1]: https://www.w3.org/TR/WCAG21/#contrast-minimum
335
+ [2]: https://www.w3.org/TR/WCAG21/#non-text-contrast
336
+ [3]: https://www.w3.org/TR/WCAG21/#focus-visible
337
+ [4]: https://www.w3.org/TR/WCAG21/#keyboard-accessible
338
+
339
+
@@ -0,0 +1,340 @@
1
+ # Sliding Panels
2
+
3
+ ## Examples
4
+
5
+
6
+ ### Basic
7
+
8
+ ```typescript
9
+ import React, { Component } from 'react';
10
+
11
+ import Button from '@splunk/react-ui/Button';
12
+ import ControlGroup from '@splunk/react-ui/ControlGroup';
13
+ import Heading from '@splunk/react-ui/Heading';
14
+ import P from '@splunk/react-ui/Paragraph';
15
+ import SlidingPanels from '@splunk/react-ui/SlidingPanels';
16
+ import Text from '@splunk/react-ui/Text';
17
+
18
+
19
+ class Basic extends Component<
20
+ object,
21
+ { activePanelId: string; transition: 'forward' | 'backward' }
22
+ > {
23
+ constructor(props: object) {
24
+ super(props);
25
+ this.state = {
26
+ activePanelId: 'one',
27
+ transition: 'forward',
28
+ };
29
+ }
30
+
31
+ goBack = () => {
32
+ this.setState((state) => ({
33
+ activePanelId: state.activePanelId === 'one' ? 'two' : 'one',
34
+ transition: 'backward',
35
+ }));
36
+ };
37
+
38
+ goForward = () => {
39
+ this.setState((state) => ({
40
+ activePanelId: state.activePanelId === 'one' ? 'two' : 'one',
41
+ transition: 'forward',
42
+ }));
43
+ };
44
+
45
+ render() {
46
+ const { activePanelId, transition } = this.state;
47
+
48
+ return (
49
+ <div style={{ border: '1px solid #999' }}>
50
+ <SlidingPanels activePanelId={activePanelId} transition={transition}>
51
+ <SlidingPanels.Panel
52
+ key="one"
53
+ panelId="one"
54
+ style={{ width: '100%', padding: 10 }}
55
+ >
56
+ <Heading level={2}>First</Heading>
57
+ <ControlGroup
58
+ label="Field label"
59
+ tooltip="Tooltip helps explain the label."
60
+ help="This is the help text."
61
+ >
62
+ <Text canClear />
63
+ </ControlGroup>
64
+ <Button onClick={this.goBack}>Prev</Button>
65
+ <Button appearance="primary" onClick={this.goForward}>
66
+ Next
67
+ </Button>
68
+ </SlidingPanels.Panel>
69
+ <SlidingPanels.Panel
70
+ key="two"
71
+ panelId="two"
72
+ style={{ width: '100%', padding: 10 }}
73
+ >
74
+ <Heading level={2}>Second</Heading>
75
+ <P>
76
+ This is some content inside the second panel. You can add more details
77
+ here as needed.
78
+ </P>
79
+ <ControlGroup
80
+ label="Field label"
81
+ tooltip="Tooltip helps explain the label."
82
+ help="This is the help text."
83
+ >
84
+ <Text canClear />
85
+ </ControlGroup>
86
+ <Button onClick={this.goBack}>Prev</Button>
87
+ <Button appearance="primary" onClick={this.goForward}>
88
+ Next
89
+ </Button>
90
+ </SlidingPanels.Panel>
91
+ </SlidingPanels>
92
+ </div>
93
+ );
94
+ }
95
+ }
96
+
97
+ export default Basic;
98
+ ```
99
+
100
+
101
+
102
+ ### In a Dropdown
103
+
104
+ ```typescript
105
+ import React, { Component } from 'react';
106
+
107
+ import ChevronLeft from '@splunk/react-icons/ChevronLeft';
108
+ import Button from '@splunk/react-ui/Button';
109
+ import Dropdown, { DropdownPossibleCloseReason } from '@splunk/react-ui/Dropdown';
110
+ import Menu from '@splunk/react-ui/Menu';
111
+ import SlidingPanels from '@splunk/react-ui/SlidingPanels';
112
+
113
+
114
+ class DropdownExample extends Component<
115
+ object,
116
+ { activePanelId: string; transition: 'forward' | 'backward' }
117
+ > {
118
+ constructor(props: object) {
119
+ super(props);
120
+ this.state = {
121
+ activePanelId: 'one',
122
+ transition: 'forward',
123
+ };
124
+ }
125
+
126
+ goBack = () => {
127
+ this.setState((state) => ({
128
+ activePanelId: state.activePanelId === 'one' ? 'two' : 'one',
129
+ transition: 'backward',
130
+ }));
131
+ };
132
+
133
+ goForward = () => {
134
+ this.setState((state) => ({
135
+ activePanelId: state.activePanelId === 'one' ? 'two' : 'one',
136
+ transition: 'forward',
137
+ }));
138
+ };
139
+
140
+ render() {
141
+ const { activePanelId, transition } = this.state;
142
+ const toggle = <Button isMenu />;
143
+ const closeReasons: DropdownPossibleCloseReason[] = [
144
+ 'clickAway',
145
+ 'escapeKey',
146
+ 'offScreen',
147
+ 'toggleClick',
148
+ ];
149
+ return (
150
+ <Dropdown closeReasons={closeReasons} toggle={toggle}>
151
+ <SlidingPanels activePanelId={activePanelId} transition={transition}>
152
+ <SlidingPanels.Panel key="one" panelId="one">
153
+ <Menu style={{ width: 160 }}>
154
+ <Menu.Item hasSubmenu onClick={this.goForward}>
155
+ Category 1
156
+ </Menu.Item>
157
+ <Menu.Item hasSubmenu onClick={this.goForward}>
158
+ Category 2
159
+ </Menu.Item>
160
+ <Menu.Item hasSubmenu onClick={this.goForward}>
161
+ Category 3
162
+ </Menu.Item>
163
+ <Menu.Item hasSubmenu onClick={this.goForward}>
164
+ Category 4
165
+ </Menu.Item>
166
+ <Menu.Item hasSubmenu onClick={this.goForward}>
167
+ Category 5
168
+ </Menu.Item>
169
+ <Menu.Item hasSubmenu onClick={this.goForward}>
170
+ Category 6
171
+ </Menu.Item>
172
+ <Menu.Item hasSubmenu onClick={this.goForward}>
173
+ Category 7
174
+ </Menu.Item>
175
+ <Menu.Item hasSubmenu onClick={this.goForward}>
176
+ Category 8
177
+ </Menu.Item>
178
+ </Menu>
179
+ </SlidingPanels.Panel>
180
+ <SlidingPanels.Panel key="two" panelId="two">
181
+ <Menu style={{ width: 160 }}>
182
+ <Menu.Item startAdornment={<ChevronLeft />} onClick={this.goBack}>
183
+ Back
184
+ </Menu.Item>
185
+ <Menu.Divider />
186
+ <Menu.Item>Option 1</Menu.Item>
187
+ <Menu.Item>Option 2</Menu.Item>
188
+ <Menu.Item>Option 3</Menu.Item>
189
+ <Menu.Item>Option 4</Menu.Item>
190
+ <Menu.Item>Option 5</Menu.Item>
191
+ <Menu.Item>Option 6</Menu.Item>
192
+ <Menu.Item>Option 7</Menu.Item>
193
+ </Menu>
194
+ </SlidingPanels.Panel>
195
+ </SlidingPanels>
196
+ </Dropdown>
197
+ );
198
+ }
199
+ }
200
+
201
+ export default DropdownExample;
202
+ ```
203
+
204
+
205
+
206
+ ### In a Modal
207
+
208
+ ```typescript
209
+ import React, { useRef, useState } from 'react';
210
+
211
+ import Button from '@splunk/react-ui/Button';
212
+ import CollapsiblePanel from '@splunk/react-ui/CollapsiblePanel';
213
+ import ControlGroup from '@splunk/react-ui/ControlGroup';
214
+ import Heading from '@splunk/react-ui/Heading';
215
+ import Modal from '@splunk/react-ui/Modal';
216
+ import P from '@splunk/react-ui/Paragraph';
217
+ import SlidingPanels from '@splunk/react-ui/SlidingPanels';
218
+ import Text from '@splunk/react-ui/Text';
219
+
220
+
221
+ function ModalExample() {
222
+ const [activePanelId, setActivePanelId] = useState<string>('one');
223
+ const [modalOpen, setModalOpen] = useState<boolean>(false);
224
+ const [transition, setTransition] = useState<'forward' | 'backward'>('forward');
225
+ const modalToggle = useRef<HTMLButtonElement | null>(null);
226
+
227
+ const goBack = () => {
228
+ setActivePanelId(activePanelId === 'one' ? 'two' : 'one');
229
+ setTransition('backward');
230
+ };
231
+
232
+ const goForward = () => {
233
+ setActivePanelId(activePanelId === 'one' ? 'two' : 'one');
234
+ setTransition('forward');
235
+ };
236
+
237
+ const open = () => {
238
+ setModalOpen(true);
239
+ };
240
+
241
+ const close = () => {
242
+ setModalOpen(false);
243
+ };
244
+
245
+ return (
246
+ <div>
247
+ <Button elementRef={modalToggle} label="Open modal" onClick={open} />
248
+ <Modal returnFocus={modalToggle} onRequestClose={close} open={modalOpen}>
249
+ <Modal.Header title="SlidingPanels in a Modal" />
250
+ <Modal.Body style={{ padding: 0 }}>
251
+ <SlidingPanels activePanelId={activePanelId} transition={transition}>
252
+ <SlidingPanels.Panel
253
+ key="one"
254
+ panelId="one"
255
+ style={{ padding: 20, width: 350 }}
256
+ >
257
+ <Heading level={2}>First</Heading>
258
+ <ControlGroup
259
+ label="Field Label"
260
+ tooltip="Tooltip helps explain the label."
261
+ help="This is the help text."
262
+ >
263
+ <Text canClear />
264
+ </ControlGroup>
265
+ </SlidingPanels.Panel>
266
+ <SlidingPanels.Panel
267
+ key="two"
268
+ panelId="two"
269
+ style={{ padding: 20, width: 800 }}
270
+ >
271
+ <CollapsiblePanel title="Sub Section">
272
+ <P>This is some content inside the sub section panel.</P>
273
+ <ControlGroup
274
+ label="Field Label"
275
+ tooltip="Tooltip helps explain the label."
276
+ help="This is the help text."
277
+ >
278
+ <Text canClear />
279
+ </ControlGroup>
280
+ </CollapsiblePanel>
281
+ <CollapsiblePanel title="Sub Section">
282
+ <P>Additional content for the second sub section.</P>
283
+ </CollapsiblePanel>
284
+ </SlidingPanels.Panel>
285
+ </SlidingPanels>
286
+ </Modal.Body>
287
+ <Modal.Footer>
288
+ <Button onClick={goBack}>Prev</Button>
289
+ <Button appearance="primary" onClick={goForward}>
290
+ Next
291
+ </Button>
292
+ </Modal.Footer>
293
+ </Modal>
294
+ </div>
295
+ );
296
+ }
297
+
298
+ export default ModalExample;
299
+ ```
300
+
301
+
302
+
303
+
304
+ ## API
305
+
306
+
307
+ ### SlidingPanels API
308
+
309
+ #### Props
310
+
311
+ | Name | Type | Required | Default | Description |
312
+ |------|------|------|------|------|
313
+ | activePanelId | string \| number | yes | | |
314
+ | children | React.ReactNode | no | | |
315
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
316
+ | innerClassName | string | no | | An additional className to inner container. |
317
+ | innerStyle | React.CSSProperties | no | | |
318
+ | onAnimationEnd | () => void | no | | |
319
+ | outerClassName | string | no | | An additional className to outer container. |
320
+ | outerStyle | React.CSSProperties | no | | |
321
+ | transition | 'forward' \| 'backward' | no | 'forward' | Direction to slide the panel |
322
+
323
+
324
+
325
+ ### SlidingPanels.Panel API
326
+
327
+ Container for arbitrary content.
328
+
329
+ #### Props
330
+
331
+ | Name | Type | Required | Default | Description |
332
+ |------|------|------|------|------|
333
+ | children | React.ReactNode | no | | |
334
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
335
+ | panelId | string \| number | yes | | A unique `id` for this panel and used by the SlidingPanels to keep track of the open panel. |
336
+
337
+
338
+
339
+
340
+