@splunk/react-ui 5.7.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Accordion.js +6 -6
- package/Box.js +83 -34
- package/CHANGELOG.md +34 -0
- package/CollapsiblePanel.js +11 -11
- package/ComboBox.js +31 -27
- package/ControlGroup.js +92 -91
- package/DefinitionList.js +9 -9
- package/Drawer.d.ts +2 -0
- package/Drawer.js +679 -0
- package/DualListbox.js +1 -1
- package/JSONTree.js +73 -72
- package/Link.js +2 -2
- package/MIGRATION.md +10 -0
- package/Menu.js +338 -240
- package/Modal.js +127 -109
- package/Multiselect.js +437 -351
- package/Paginator.js +14 -12
- package/Popover.js +4 -1
- package/README.md +11 -0
- package/RadioBar.js +1 -1
- package/Search.js +103 -88
- package/Select.js +42 -40
- package/SelectBase.js +374 -328
- package/SidePanel.js +346 -167
- package/SlidingPanels.js +11 -11
- package/StepBar.js +7 -7
- package/Switch.js +5 -5
- package/Text.js +24 -24
- package/TextArea.js +7 -7
- package/TransitionOpen.js +204 -185
- package/docs-llm/Accordion.md +267 -0
- package/docs-llm/Anchor Menu.md +115 -0
- package/docs-llm/Anchor.md +54 -0
- package/docs-llm/AnimationToggle.md +254 -0
- package/docs-llm/Avatar.md +298 -0
- package/docs-llm/Badge.md +212 -0
- package/docs-llm/Breadcrumbs.md +306 -0
- package/docs-llm/Button Group.md +53 -0
- package/docs-llm/Button.md +361 -0
- package/docs-llm/Card Layout.md +286 -0
- package/docs-llm/Card.md +619 -0
- package/docs-llm/Checkbox.md +218 -0
- package/docs-llm/Chip.md +291 -0
- package/docs-llm/Clickable.md +160 -0
- package/docs-llm/Code.md +292 -0
- package/docs-llm/Collapsible Panel.md +744 -0
- package/docs-llm/Color.md +253 -0
- package/docs-llm/Column Layout.md +391 -0
- package/docs-llm/Combo Box.md +540 -0
- package/docs-llm/Control Group.md +594 -0
- package/docs-llm/Date.md +270 -0
- package/docs-llm/Definition List.md +278 -0
- package/docs-llm/Divider.md +216 -0
- package/docs-llm/Drawer.md +414 -0
- package/docs-llm/Dropdown.md +472 -0
- package/docs-llm/Dual Listbox.md +325 -0
- package/docs-llm/File.md +653 -0
- package/docs-llm/Form Rows.md +374 -0
- package/docs-llm/Heading.md +179 -0
- package/docs-llm/Image.md +109 -0
- package/docs-llm/JSON Tree.md +260 -0
- package/docs-llm/Layer.md +74 -0
- package/docs-llm/Layout.md +50 -0
- package/docs-llm/Link.md +318 -0
- package/docs-llm/List.md +189 -0
- package/docs-llm/Markdown.md +179 -0
- package/docs-llm/Menu.md +735 -0
- package/docs-llm/Message Bar.md +236 -0
- package/docs-llm/Message.md +248 -0
- package/docs-llm/Modal.md +443 -0
- package/docs-llm/Monogram.md +159 -0
- package/docs-llm/Multiselect.md +937 -0
- package/docs-llm/Number.md +298 -0
- package/docs-llm/Paginator.md +395 -0
- package/docs-llm/Paragraph.md +148 -0
- package/docs-llm/Phone Number.md +254 -0
- package/docs-llm/Popover.md +166 -0
- package/docs-llm/Progress.md +141 -0
- package/docs-llm/Radio Bar.md +303 -0
- package/docs-llm/Radio List.md +350 -0
- package/docs-llm/Resize.md +362 -0
- package/docs-llm/Screen Reader Content.md +73 -0
- package/docs-llm/Scroll Container Context.md +155 -0
- package/docs-llm/Scroll.md +152 -0
- package/docs-llm/Search.md +381 -0
- package/docs-llm/Select.md +985 -0
- package/docs-llm/Side Panel.md +777 -0
- package/docs-llm/Slider.md +339 -0
- package/docs-llm/Sliding Panels.md +340 -0
- package/docs-llm/Split Button.md +295 -0
- package/docs-llm/Static Content.md +90 -0
- package/docs-llm/Step Bar.md +292 -0
- package/docs-llm/Switch.md +268 -0
- package/docs-llm/Tab Bar.md +439 -0
- package/docs-llm/Tab Layout.md +398 -0
- package/docs-llm/Table.md +2642 -0
- package/docs-llm/Text Area.md +253 -0
- package/docs-llm/Text.md +339 -0
- package/docs-llm/Tooltip.md +325 -0
- package/docs-llm/Transition Open.md +406 -0
- package/docs-llm/Tree.md +586 -0
- package/docs-llm/Typography.md +125 -0
- package/docs-llm/Wait Spinner.md +121 -0
- package/docs-llm/llms.txt +97 -0
- package/package.json +6 -5
- package/types/src/Box/Box.d.ts +2 -10
- package/types/src/Drawer/Body.d.ts +17 -0
- package/types/src/Drawer/Drawer.d.ts +114 -0
- package/types/src/Drawer/DrawerContext.d.ts +11 -0
- package/types/src/Drawer/Footer.d.ts +25 -0
- package/types/src/Drawer/Header.d.ts +41 -0
- package/types/src/Drawer/docs/examples/Basic.d.ts +6 -0
- package/types/src/Drawer/docs/examples/ContainerPosition.d.ts +7 -0
- package/types/src/Drawer/docs/examples/InitialFocus.d.ts +9 -0
- package/types/src/Drawer/docs/examples/InlinePosition.d.ts +7 -0
- package/types/src/Drawer/docs/examples/PagePosition.d.ts +7 -0
- package/types/src/Drawer/index.d.ts +2 -0
- package/types/src/JSONTree/JSONTree.d.ts +12 -5
- package/types/src/JSONTree/renderTreeItems.d.ts +2 -1
- package/types/src/Menu/Item.d.ts +2 -1
- package/types/src/Menu/docs/examples/SelectableCheckbox.d.ts +7 -0
- package/types/src/Modal/Modal.d.ts +1 -2
- package/types/src/Select/Option.d.ts +6 -3
- package/types/src/Select/Select.d.ts +8 -5
- package/types/src/Select/docs/examples/Dimmed.d.ts +7 -0
- package/types/src/SelectBase/OptionBase.d.ts +6 -3
- package/types/src/SelectBase/SelectBase.d.ts +8 -3
- package/types/src/SidePanel/SidePanel.d.ts +43 -2
- package/types/src/SidePanel/docs/examples/DockLayout.d.ts +17 -0
- package/types/src/SidePanel/docs/examples/InitialFocus.d.ts +9 -0
- package/types/src/TransitionOpen/TransitionOpen.d.ts +29 -4
- package/types/src/useKeyPress/index.d.ts +9 -2
- package/types/src/useOnClickOutside/index.d.ts +2 -0
- package/types/src/useOnClickOutside/useOnClickOutside.d.ts +4 -0
- package/useKeyPress.js +23 -18
- package/useOnClickOutside.d.ts +2 -0
- package/useOnClickOutside.js +79 -0
- package/types/src/RadioList/docs/examples/Row.d.ts +0 -6
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# Modal
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
> Image: Illustration of a Modal component
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## When to use this component
|
|
10
|
+
Modals create a new context for users, similar to navigating to a new page. This makes them inherently disruptive to a workflow as they disable everything on the page until dismissed. Modals should be used sparingly, thoughtfully, and only when an isolated or focused context is necessary to continue a task. Only use them in the following cases:
|
|
11
|
+
|
|
12
|
+
- When you need to show important content that the user needs to interact with before they can continue.
|
|
13
|
+
- When there is a choice that the user must make immediately or a small amount of information the user must provide.
|
|
14
|
+
- When you need to intentionally block progress and require confirmation for destructive actions.
|
|
15
|
+
|
|
16
|
+
## When to use another component
|
|
17
|
+
- If multiple tasks or steps are required to exit a modal, take the user to a separate page instead.
|
|
18
|
+
- When the information is not crucial for the user to interact with, display it on the main page without interrupting the user.
|
|
19
|
+
- When the modal would be too disruptive to the user's experience, such as if it pops up unexpectedly or covers up too much of the main page, use a less intrusive component such as a `Message`, `Popover`, or `Tooltip`.
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
graph TD
|
|
23
|
+
accDescr: Decision tree that guides on when to use the Modal component or something else
|
|
24
|
+
A(Requires immediate attention, input, or confirmation?) -- Yes --- B(Content long, requires multiple steps?)
|
|
25
|
+
B -- Yes --- C(Use a separate page or section)
|
|
26
|
+
B -- No --- D(Use a modal)
|
|
27
|
+
A -- No --- E(Use a tooltip, popover, or message)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Check out
|
|
31
|
+
- [Message] [1]
|
|
32
|
+
- [Popover] [2]
|
|
33
|
+
- [Tooltip] [3]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Close modal
|
|
39
|
+
Provide a clear and recognizable way for users to close the modal:
|
|
40
|
+
- **Escape key**: Pressing <kbd>Esc</kbd> must close the modal. This behavior cannot be overridden.
|
|
41
|
+
- **Close button**: A close button should be rendered in the top right corner of the modal.
|
|
42
|
+
|
|
43
|
+
> Image: Examples of a clear method for closing a modal: The first example, which includes a heart eyes emoji, features a close button in the top right corner of the modal and a button group in the bottom right offering both primary and secondary actions. The second example, with a grimacing face emoji, lacks a close button in the top right corner of the modal and only has a button group providing a primary and secondary action.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### Clicking outside to dismiss
|
|
47
|
+
|
|
48
|
+
By default, clicking outside of a modal does not close the modal.
|
|
49
|
+
|
|
50
|
+
This is an intentional design decision to prevent accidental dismissal, which can result in data loss or disruption of a workflow. A modal should always provide a clear, intentional way to be closed, such as the Escape key or a close button.
|
|
51
|
+
|
|
52
|
+
In specific, limited scenarios, it may be appropriate to allow clicking outside the modal to dismiss it by enabling the `closeOnClickAway` prop.
|
|
53
|
+
|
|
54
|
+
#### When this may be appropriate
|
|
55
|
+
Only consider enabling click outside to dismiss when all of the following are true:
|
|
56
|
+
- The modal content is non-critical or purely informational
|
|
57
|
+
- Accidental dismissal will not result in loss of data, progress, or important context
|
|
58
|
+
- The modal behaves like a transient or lightweight interface, such as global search or a command palette
|
|
59
|
+
|
|
60
|
+
#### When not to use this behavior
|
|
61
|
+
Avoid enabling click outside to dismiss for:
|
|
62
|
+
- Forms or workflows with user input
|
|
63
|
+
- Multi-step or stateful interactions
|
|
64
|
+
- Destructive or confirmation dialogs
|
|
65
|
+
- Any modal where dismissal could lead to confusion or loss of work
|
|
66
|
+
|
|
67
|
+
### Primary action
|
|
68
|
+
The final interactive element in a modal should be the primary action.
|
|
69
|
+
> Image: Examples illustrating the placement of a primary action in modals. The first example, marked with a heart eyes emoji, displays a modal with a button group located in the bottom right corner; this group includes both primary and secondary actions, with the primary action designated as the second button. The second example, identified by a grimacing face emoji, presents a modal with a secondary button in the bottom right and a button group in the bottom left corner for primary and tertiary actions. In the group, the primary action is again the second button.
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
### Workflow
|
|
73
|
+
If multiple tasks are required, take the user to a separate page instead of a modal.
|
|
74
|
+
> Image: Examples illustrating the management of multiple tasks or steps in a user interface. The first example, represented by a heart eyes emoji, displays a step pattern located directly under the page title, signifying a recommended approach for task progression. The second example, marked with a grimacing face emoji, shows the step pattern placed within a modal, an approach that is not recommended.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Messages in modals
|
|
78
|
+
`MessageBar` or `Message` components should be placed after the modal header. Neither the message bar or message should use the `isDismissible` prop because it would conflict with the close or dismiss actions for the modal.
|
|
79
|
+
> Image: Examples illustrating using the `Message` or `MessageBar` component in a modal. The first example with a heart eye emoji displays the `MessageBar` below the modal header. The second example with a grimacing face emoji displays the `MessageBar` at the top of the modal above the modal header.
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
### Disabled elements
|
|
83
|
+
Avoid disabling buttons or inputs in modals. Enable them and show an error text in-line or in a summary at the top of the modal.
|
|
84
|
+
> Image: Examples of disabling buttons or inputs in modals, and use error text and validation instead. The first example with heart eyes emoji has a modal with two inputs in the modal body followed by a button group in the bottom right. All inputs and buttons are enabled and the first input is in an error state with error text. The second example with a grimacing face emoji, has two inputs in the modal body follow by the button group in the bottom right. The buttons in this example are disabled and it
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Clear content
|
|
88
|
+
Make sure that the content inside the modal is clearly related to the action that triggered the modal to appear, since users do not have access to the content from the page.
|
|
89
|
+
> Image: Examples of modal titles that are brief and provide context. The first example with heart eyes emoji has a modal with a title of
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Content
|
|
93
|
+
|
|
94
|
+
### Title
|
|
95
|
+
Write a brief title in the form of a statement or question that clearly describes the task the user is completing in the modal. Use a verb plus noun combination when possible.
|
|
96
|
+
> Image: Content examples for modal titles in the form of a statement or question. The first example with heart eyes emoji reads
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#### Sentence style
|
|
100
|
+
Use sentence-style capitalization and capitalize the first word and proper nouns only.
|
|
101
|
+
> Image: Content examples of using sentence style in modal titles. The first with heart eyes emoji reads
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### Body text
|
|
105
|
+
Include only content that is directly related to completing the task at hand. Don’t repeat or rephrase the title.
|
|
106
|
+
> Image: Content example for Modal body text that is related to the task at hand. The first example with heart eyes emoji that reads
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
#### Clear context
|
|
110
|
+
Provide context that helps the user decide which action to take.
|
|
111
|
+
> Image: Content example for Modal content that helps users decide which actions to take. The first example with heart eyes emoji reads
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
### Actions
|
|
115
|
+
Use a precise verb to describe the action instead of vague words like Done or OK when possible.
|
|
116
|
+
> Image: Content example for actions in Modals using a precise verb. The first example with heart eyes emoji reads
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
[1]: ./Message
|
|
120
|
+
[2]: ./Popover
|
|
121
|
+
[3]: ./Tooltip
|
|
122
|
+
|
|
123
|
+
## Examples
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
### Basic
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import React, { useRef, useState } from 'react';
|
|
130
|
+
|
|
131
|
+
import Button from '@splunk/react-ui/Button';
|
|
132
|
+
import Modal from '@splunk/react-ui/Modal';
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
function Basic() {
|
|
136
|
+
const [open, setOpen] = useState(false);
|
|
137
|
+
const modalToggle = useRef<HTMLButtonElement | null>(null);
|
|
138
|
+
|
|
139
|
+
const handleRequestOpen = () => {
|
|
140
|
+
setOpen(true);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const handleRequestClose = () => {
|
|
144
|
+
setOpen(false);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<Button onClick={handleRequestOpen} elementRef={modalToggle} label="Click me" />
|
|
150
|
+
<Modal returnFocus={modalToggle} onRequestClose={handleRequestClose} open={open}>
|
|
151
|
+
<Modal.Header title="Simple dialog" />
|
|
152
|
+
<Modal.Body>
|
|
153
|
+
Modals create a new context for users, similar to navigating to a new page.
|
|
154
|
+
</Modal.Body>
|
|
155
|
+
</Modal>
|
|
156
|
+
</>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export default Basic;
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
### Typical usage
|
|
166
|
+
|
|
167
|
+
This example shows a basic Splunk UI-styled Modal. By default, the Modal takes on the width of the content, so ensure that the width is set on the children. Alternately, set width on the Modal or Modal.Body with an inline style. Use an inline style to set the width and height of the icon to fit the icon's container. Modals *must* return focus to the element that invoked the dialog (or another element that follows the logical flow of the application) on close. To automatically return focus to the invoking element on Modal close, pass the ref of the invoking element to Modal's returnFocus prop. If using a ref is not possible, you *must* manually return focus to the invoking element in a function passed to returnFocus. Additionally, Modals containing a form should not close when clickAway event occurs. See below for an example of how to implement these requirements.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import React, { useState, useRef } from 'react';
|
|
171
|
+
|
|
172
|
+
import Layout from '@splunk/react-icons/Layout';
|
|
173
|
+
import Button from '@splunk/react-ui/Button';
|
|
174
|
+
import ControlGroup from '@splunk/react-ui/ControlGroup';
|
|
175
|
+
import Modal from '@splunk/react-ui/Modal';
|
|
176
|
+
import P from '@splunk/react-ui/Paragraph';
|
|
177
|
+
import Select from '@splunk/react-ui/Select';
|
|
178
|
+
import Text from '@splunk/react-ui/Text';
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
function TypicalUsage() {
|
|
182
|
+
const modalToggle = useRef<HTMLButtonElement | null>(null);
|
|
183
|
+
|
|
184
|
+
const [open, setOpen] = useState(false);
|
|
185
|
+
|
|
186
|
+
const handleRequestOpen = () => {
|
|
187
|
+
setOpen(true);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const handleRequestClose = () => {
|
|
191
|
+
setOpen(false);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<>
|
|
196
|
+
<Button onClick={handleRequestOpen} elementRef={modalToggle} label="Click me" />
|
|
197
|
+
<Modal
|
|
198
|
+
onRequestClose={handleRequestClose}
|
|
199
|
+
open={open}
|
|
200
|
+
returnFocus={modalToggle}
|
|
201
|
+
style={{ width: '600px' }}
|
|
202
|
+
>
|
|
203
|
+
<form>
|
|
204
|
+
<Modal.Header
|
|
205
|
+
title="Header"
|
|
206
|
+
subtitle="Similar to cards, modals consist of three major parts."
|
|
207
|
+
icon={<Layout />}
|
|
208
|
+
/>
|
|
209
|
+
<Modal.Body>
|
|
210
|
+
<P>
|
|
211
|
+
This is an example of modal body content. Please fill out the form
|
|
212
|
+
below.
|
|
213
|
+
</P>
|
|
214
|
+
<ControlGroup label="First Name">
|
|
215
|
+
<Text />
|
|
216
|
+
</ControlGroup>
|
|
217
|
+
<ControlGroup label="Last Name" controlsLayout="fillJoin">
|
|
218
|
+
<Text />
|
|
219
|
+
</ControlGroup>
|
|
220
|
+
<ControlGroup label="Office" tooltip="The office you are assigned to.">
|
|
221
|
+
<Select defaultValue="sf">
|
|
222
|
+
<Select.Option label="San Francisco" value="sf" />
|
|
223
|
+
<Select.Option label="Santana Row" value="sr" />
|
|
224
|
+
</Select>
|
|
225
|
+
</ControlGroup>
|
|
226
|
+
</Modal.Body>
|
|
227
|
+
<Modal.Footer>
|
|
228
|
+
<Button
|
|
229
|
+
appearance="secondary"
|
|
230
|
+
onClick={handleRequestClose}
|
|
231
|
+
label="Cancel"
|
|
232
|
+
/>
|
|
233
|
+
<Button appearance="primary" label="Submit" type="submit" />
|
|
234
|
+
</Modal.Footer>
|
|
235
|
+
</form>
|
|
236
|
+
</Modal>
|
|
237
|
+
</>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export default TypicalUsage;
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
### Undismissable
|
|
247
|
+
|
|
248
|
+
To create a Modal that cannot be dismissed, omit the onClose callback.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
252
|
+
|
|
253
|
+
import Button from '@splunk/react-ui/Button';
|
|
254
|
+
import Modal from '@splunk/react-ui/Modal';
|
|
255
|
+
import ScreenReaderContent from '@splunk/react-ui/ScreenReaderContent';
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
function Basic() {
|
|
259
|
+
const modalToggle = useRef<HTMLButtonElement | null>(null);
|
|
260
|
+
const counterInterval = useRef<() => void>();
|
|
261
|
+
const [count, setCount] = useState(5);
|
|
262
|
+
const [open, setOpen] = useState(false);
|
|
263
|
+
const [wasOpen, setWasOpen] = useState(false);
|
|
264
|
+
|
|
265
|
+
const handleCounter = () => {
|
|
266
|
+
const newCount = count - 1;
|
|
267
|
+
if (newCount === 0) {
|
|
268
|
+
setOpen(false);
|
|
269
|
+
setWasOpen(true);
|
|
270
|
+
} else {
|
|
271
|
+
setCount(newCount);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
counterInterval.current = handleCounter;
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// eslint-disable-next-line consistent-return
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
const tick = () => {
|
|
282
|
+
counterInterval?.current?.();
|
|
283
|
+
};
|
|
284
|
+
if (open) {
|
|
285
|
+
setCount(5);
|
|
286
|
+
const id = window.setInterval(tick, 1000);
|
|
287
|
+
return () => {
|
|
288
|
+
window.clearInterval(id);
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}, [open]);
|
|
292
|
+
|
|
293
|
+
const handleRequestOpen = () => {
|
|
294
|
+
setOpen(true);
|
|
295
|
+
setWasOpen(false);
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<div>
|
|
300
|
+
{/* Use an aria-live element that is visually hidden to announce when the modal is automatically dismissed */}
|
|
301
|
+
<ScreenReaderContent aria-atomic="true" aria-live="assertive">
|
|
302
|
+
{wasOpen ? 'Modal has been automatically dismissed' : ''}
|
|
303
|
+
</ScreenReaderContent>
|
|
304
|
+
<Button onClick={handleRequestOpen} elementRef={modalToggle} label="Click me" />
|
|
305
|
+
<Modal returnFocus={modalToggle} open={open}>
|
|
306
|
+
<Modal.Body>
|
|
307
|
+
This modal cannot be dismissed by the user. It will be dismissed in {count}{' '}
|
|
308
|
+
seconds.
|
|
309
|
+
</Modal.Body>
|
|
310
|
+
</Modal>
|
|
311
|
+
</div>
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
export default Basic;
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
### Initial focus
|
|
320
|
+
|
|
321
|
+
Initial focus can be set to an different element.
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
import React, { useCallback, useState, useRef } from 'react';
|
|
325
|
+
|
|
326
|
+
import Button from '@splunk/react-ui/Button';
|
|
327
|
+
import Modal from '@splunk/react-ui/Modal';
|
|
328
|
+
import P from '@splunk/react-ui/Paragraph';
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
function InitialFocus() {
|
|
332
|
+
const [acceptButton, setAcceptButon] = useState<HTMLButtonElement>();
|
|
333
|
+
const acceptButtonRef = useCallback((el: HTMLButtonElement) => setAcceptButon(el), []);
|
|
334
|
+
|
|
335
|
+
const [open, setOpen] = useState(false);
|
|
336
|
+
const modalToggle = useRef<HTMLButtonElement | null>(null);
|
|
337
|
+
|
|
338
|
+
const handleRequestOpen = () => {
|
|
339
|
+
setOpen(true);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const handleRequestClose = () => {
|
|
343
|
+
setOpen(false);
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
return (
|
|
347
|
+
<>
|
|
348
|
+
<Button onClick={handleRequestOpen} elementRef={modalToggle} label="Click me" />
|
|
349
|
+
<Modal
|
|
350
|
+
initialFocus={acceptButton}
|
|
351
|
+
onRequestClose={handleRequestClose}
|
|
352
|
+
open={open}
|
|
353
|
+
returnFocus={modalToggle}
|
|
354
|
+
style={{ width: '600px' }}
|
|
355
|
+
>
|
|
356
|
+
<Modal.Header title="Header" />
|
|
357
|
+
<Modal.Body>
|
|
358
|
+
<P>This modal demonstrates how to set initial focus to a specific element.</P>
|
|
359
|
+
</Modal.Body>
|
|
360
|
+
<Modal.Footer>
|
|
361
|
+
<Button appearance="secondary" onClick={handleRequestClose} label="Cancel" />
|
|
362
|
+
<Button appearance="primary" elementRef={acceptButtonRef} label="Accept" />
|
|
363
|
+
</Modal.Footer>
|
|
364
|
+
</Modal>
|
|
365
|
+
</>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export default InitialFocus;
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
## API
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
### Modal API
|
|
379
|
+
|
|
380
|
+
#### Props
|
|
381
|
+
|
|
382
|
+
| Name | Type | Required | Default | Description |
|
|
383
|
+
|------|------|------|------|------|
|
|
384
|
+
| children | React.ReactNode | no | | Any renderable children can be passed to the `Modal`. To use the default Splunk UI `Modal` styles, use the `Modal.Header`, `Modal.Body`, and `Modal.Footer`. |
|
|
385
|
+
| closeOnClickAway | boolean | no | | Set to 'true' to enable closing the Modal by clicking outside of it. This behavior should be avoided as it can lead to accidental dismissal of the modal causing data loss or disruption of a user's workflow. Only enable click outside to dismiss when: - The modal content is non-critical or purely informational - Accidental dismissal will not result in loss of progress, data, or important context `onRequestClose` will receive an event with reason 'clickAway' when this happens. |
|
|
386
|
+
| divider | 'header' \| 'footer' \| 'both' \| 'none' | no | 'both' | Show dividers between header, body and footer. |
|
|
387
|
+
| elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
|
|
388
|
+
| initialFocus | \| 'first' \| 'container' \| (React.Component & { focus: () => void }) \| HTMLElement \| null | no | 'first' | Allows focus to be set to a component other than the default. Supports `first` (first focusable element in the modal), `container` (focus the modal itself), or a ref. |
|
|
389
|
+
| onRequestClose | ModalRequestCloseHandler | no | | Called when a close event occurs. When `Modal` includes this prop, a close button is displayed by default in the `Modal.Header`. To hide the close button, pass the `hideCloseButton` prop to `Modal.Header`. The callback is passed the event and a reason, which is 'escapeKey', 'clickAway', or 'clickCloseButton'. Generally, use this callback to toggle the `open` prop. |
|
|
390
|
+
| open | boolean | no | false | Set to `true` if the `Modal` is currently open. Otherwise, set to `false`. |
|
|
391
|
+
| returnFocus | \| React.MutableRefObject<(React.Component & { focus: () => void }) \| HTMLElement \| null> \| (() => void) | yes | | Pass the ref of the invoking element (or other element that follows the logical flow of the application) to automatically move focus to the invoking element on `Modal` close. If using a ref is not possible, you *must* pass a function that sets focus to the appropriate element. This function will be called after `onRequestClose`. |
|
|
392
|
+
|
|
393
|
+
#### Types
|
|
394
|
+
|
|
395
|
+
| Name | Type | Description |
|
|
396
|
+
|------|------|------|
|
|
397
|
+
| ModalRequestCloseHandler | (data: { event: \| React.MouseEvent<HTMLDivElement \| HTMLAnchorElement \| HTMLButtonElement> \| MouseEvent \| KeyboardEvent \| TouchEvent; reason: 'clickAway' \| 'escapeKey' \| 'clickCloseButton'; }) => void | |
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
### Modal.Header API
|
|
402
|
+
|
|
403
|
+
A styled container for `Modal` header content.
|
|
404
|
+
|
|
405
|
+
#### Props
|
|
406
|
+
|
|
407
|
+
| Name | Type | Required | Default | Description |
|
|
408
|
+
|------|------|------|------|------|
|
|
409
|
+
| children | React.ReactNode | no | | `children` might be passed instead of a title. Note that `children` aren't rendered if a title is provided. |
|
|
410
|
+
| hideCloseButton | boolean | no | false | Hide the closeButton in the Header if `onRequestClose` is provided to `Modal`. |
|
|
411
|
+
| icon | React.ReactNode | no | | The icon to show before the title. |
|
|
412
|
+
| subtitle | React.ReactNode | no | | Used as the subheading. Only shown if `title` is also present. |
|
|
413
|
+
| title | string | no | | Used as the main heading. |
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
### Modal.Body API
|
|
418
|
+
|
|
419
|
+
A styled container for `Modal` body content.
|
|
420
|
+
|
|
421
|
+
#### Props
|
|
422
|
+
|
|
423
|
+
| Name | Type | Required | Default | Description |
|
|
424
|
+
|------|------|------|------|------|
|
|
425
|
+
| children | React.ReactNode | no | | |
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
### Modal.Footer API
|
|
430
|
+
|
|
431
|
+
A styled container for `Modal` footer content.
|
|
432
|
+
|
|
433
|
+
#### Props
|
|
434
|
+
|
|
435
|
+
| Name | Type | Required | Default | Description |
|
|
436
|
+
|------|------|------|------|------|
|
|
437
|
+
| children | React.ReactNode | no | | |
|
|
438
|
+
| layout | 'auto' \| 'none' | no | 'auto' | Controls the layout and styling for children. `auto` will style children for common use cases, such as: buttons; controls; documentation links; or a combination. Set `none` when custom styling is needed. |
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Monogram
|
|
2
|
+
|
|
3
|
+
## Examples
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Basic
|
|
7
|
+
|
|
8
|
+
A Monogram can show one to three characters. You can use the getInitials helper to shorten a name.
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import React from 'react';
|
|
12
|
+
|
|
13
|
+
import Monogram, { getInitials } from '@splunk/react-ui/Monogram';
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export default function Basic() {
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
<Monogram initials="A" />
|
|
20
|
+
<Monogram initials="AE" />
|
|
21
|
+
<Monogram initials="AME" />
|
|
22
|
+
<Monogram initials={getInitials('Amelia')} />
|
|
23
|
+
<Monogram initials={getInitials('Amelia Earhart')} />
|
|
24
|
+
<Monogram initials={getInitials('Amelia Mary Earhart')} />
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Custom background color
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import React from 'react';
|
|
36
|
+
|
|
37
|
+
import Monogram from '@splunk/react-ui/Monogram';
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export default function BackgroundCustom() {
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<Monogram backgroundColor="cornflowerblue" initials="A" />
|
|
44
|
+
<Monogram backgroundColor="#888" initials="AE" />
|
|
45
|
+
<Monogram backgroundColor="rgb(170, 100, 120)" initials="AME" />
|
|
46
|
+
</>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Interactive
|
|
54
|
+
|
|
55
|
+
A click handler can be added to enable interactivity.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import React from 'react';
|
|
59
|
+
|
|
60
|
+
import Monogram from '@splunk/react-ui/Monogram';
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
export default function Interactive() {
|
|
64
|
+
return (
|
|
65
|
+
<>
|
|
66
|
+
<Monogram initials="A" onClick={() => {}} />
|
|
67
|
+
<Monogram initials="AE" onClick={() => {}} />
|
|
68
|
+
<Monogram initials="AME" onClick={() => {}} />
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
### Size
|
|
77
|
+
|
|
78
|
+
Monograms can be one of three standard sizes: "small", "medium" (default), "large", or "xlarge" (deprecated). The size prop can also be a number if the standard size does not fit your use case. Note: using a non-standard size may have unexpected layouts when combined with other components.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import React from 'react';
|
|
82
|
+
|
|
83
|
+
import Monogram from '@splunk/react-ui/Monogram';
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
export default function Size() {
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<div>
|
|
90
|
+
<Monogram initials="A" size="small" />
|
|
91
|
+
<Monogram initials="AE" size="small" />
|
|
92
|
+
<Monogram initials="AME" size="small" />
|
|
93
|
+
</div>
|
|
94
|
+
<div style={{ marginTop: '10px' }}>
|
|
95
|
+
<Monogram initials="A" size="medium" />
|
|
96
|
+
<Monogram initials="AE" size="medium" />
|
|
97
|
+
<Monogram initials="AME" size="medium" />
|
|
98
|
+
</div>
|
|
99
|
+
<div style={{ marginTop: '10px' }}>
|
|
100
|
+
<Monogram initials="A" size="large" />
|
|
101
|
+
<Monogram initials="AE" size="large" />
|
|
102
|
+
<Monogram initials="AME" size="large" />
|
|
103
|
+
</div>
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### Auto background color
|
|
112
|
+
|
|
113
|
+
The background color is derived from the initials prop if the backgroundColor prop is set to "auto". We do not recommend using "auto" background color because the existing built-in background color set might lead to color contrast issues. Please use a custom background color and ensure that it has sufficient color contrast with the initial's text color.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import React from 'react';
|
|
117
|
+
|
|
118
|
+
import Monogram from '@splunk/react-ui/Monogram';
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
export default function BackgroundAuto() {
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
<Monogram backgroundColor="auto" initials="A" />
|
|
125
|
+
<Monogram backgroundColor="auto" initials="AE" />
|
|
126
|
+
<Monogram backgroundColor="auto" initials="AME" />
|
|
127
|
+
</>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
## API
|
|
136
|
+
|
|
137
|
+
import React from 'react';
|
|
138
|
+
|
|
139
|
+
import ComponentAPI from '@splunk/react-docs/ComponentAPI';
|
|
140
|
+
import UtilAPI from '@splunk/react-docs/UtilAPI';
|
|
141
|
+
import Heading from '@splunk/react-ui/Heading';
|
|
142
|
+
|
|
143
|
+
import utilDocs from '!!@splunk/jsdoc-loader!@splunk/react-ui/Monogram/Monogram';
|
|
144
|
+
import allDocs from '@splunk/react-ui/Monogram/Monogram?parseDocs';
|
|
145
|
+
|
|
146
|
+
const docs = allDocs.find((doc) => doc.displayName === 'Monogram');
|
|
147
|
+
|
|
148
|
+
function DevelopSection() {
|
|
149
|
+
return [
|
|
150
|
+
<ComponentAPI title="Monogram" key="component" docs={docs} />,
|
|
151
|
+
<Heading level={4} key="utilsHeading">
|
|
152
|
+
Utils
|
|
153
|
+
</Heading>,
|
|
154
|
+
<UtilAPI title="Monogram2" key="utils" docs={utilDocs} />,
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
export default DevelopSection;
|
|
158
|
+
|
|
159
|
+
|