@neo4j-ndl/react 4.18.4 → 4.18.6

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.
@@ -9,7 +9,9 @@ Import: `import { ColorPicker } from '@neo4j-ndl/react'`
9
9
  | Prop | Type | Required | Default | Description |
10
10
  |------|------|----------|---------|-------------|
11
11
  | `color` | `` HsvaColor \| RgbaColor \| `#${string}` `` | ✅ | | The current color value. Can be provided in HSVA, RGBA, or Hex format. The component will automatically convert between formats as needed. |
12
+ | `floatingStrategy` | `'absolute' \| 'fixed'` | | `absolute` | The floating strategy to use for the menu. If not provided, the menu will be positioned absolutely. |
12
13
  | `onChange` | `` (newColor: { hex: `#${string}`; rgb: RgbaColor; hsva: HsvaColor; }) => void `` | ✅ | | Callback function triggered when the color value changes. Receives an object containing the new color in all three formats (hex, rgb, hsva) for convenience. |
14
+ | `portalTarget` | `HTMLElement \| null` | | | The target element to portal the menu to. If not provided, the menu will not be portaled. |
13
15
  | `shouldShowEyeDropper` | `boolean` | | `true` | Whether to display the eye dropper tool that allows users to sample colors from anywhere on the screen. |
14
16
  | `swatches` | `` (HsvaColor \| RgbaColor \| `#${string}`)[] `` | | `Object.values(tokens.graph).filter(validHex)` | Optional array of predefined color swatches for quick selection. Each swatch can be in HSVA, RGBA, or Hex format. |
15
17
 
@@ -103,6 +105,82 @@ const Component = () => {
103
105
  export default Component;
104
106
  ```
105
107
 
108
+ ### Dialog
109
+
110
+ ```tsx
111
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
112
+
113
+ import { ColorPicker, Dialog, FilledButton } from '@neo4j-ndl/react';
114
+ import { useState } from 'react';
115
+
116
+ const Component = () => {
117
+ const [isOpen, setIsOpen] = useState<boolean>(false);
118
+ const handleClick = () => setIsOpen((prev) => !prev);
119
+ const handleClose = () => setIsOpen(false);
120
+
121
+ const [color, setColor] = useState({
122
+ a: 1,
123
+ b: 0,
124
+ g: 0,
125
+ r: 0,
126
+ });
127
+
128
+ return (
129
+ <div className="n-flex n-items-center n-justify-centern-w-full">
130
+ <FilledButton
131
+ onClick={handleClick}
132
+ htmlAttributes={{ 'aria-haspopup': 'dialog' }}
133
+ >
134
+ Open Dialog
135
+ </FilledButton>
136
+ <Dialog onClose={handleClose} isOpen={isOpen}>
137
+ <Dialog.Header>Header</Dialog.Header>
138
+ <Dialog.Content className="n-max-h-96 n-overflow-y-auto">
139
+ <ColorPicker
140
+ color={color}
141
+ onChange={(newColor) => setColor(newColor.rgb)}
142
+ floatingStrategy="fixed"
143
+ />
144
+ </Dialog.Content>
145
+ </Dialog>
146
+ </div>
147
+ );
148
+ };
149
+
150
+ export default Component;
151
+ ```
152
+
153
+ ### Popover
154
+
155
+ ```tsx
156
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
157
+
158
+ import { ColorPicker, FilledButton, Popover } from '@neo4j-ndl/react';
159
+
160
+ const Component = () => {
161
+ return (
162
+ <Popover>
163
+ <Popover.Trigger hasButtonWrapper>
164
+ <FilledButton>Open Popover</FilledButton>
165
+ </Popover.Trigger>
166
+ <Popover.Content className="n-overflow-y-auto n-overflow-x-hidden n-p-4 n-max-h-64">
167
+ Popover content
168
+ <ColorPicker
169
+ color="#ff0000"
170
+ onChange={() => {
171
+ console.info('color changed');
172
+ }}
173
+ floatingStrategy="fixed"
174
+ portalTarget={document.body}
175
+ />
176
+ </Popover.Content>
177
+ </Popover>
178
+ );
179
+ };
180
+
181
+ export default Component;
182
+ ```
183
+
106
184
  ### Without Eyedropper
107
185
 
108
186
  ```tsx
@@ -111,7 +111,7 @@ Implements the keyboard interactions defined in the [WAI-ARIA menu pattern](http
111
111
  | `Space` | Activates the focused menu item |
112
112
  | `Tab` | Closes the menu and moves focus to the next focusable element on the page |
113
113
  | `Shift + Tab` | Closes the menu and moves focus to the previous focusable element on the page |
114
- | `Escape` | Closes the menu and returns focus to the trigger |
114
+ | `Escape` | Closes the full menu tree and returns focus to the trigger. The event does not propagate beyond the root menu, so enclosing overlays remain open |
115
115
  | Type-ahead | Typing a character moves focus to the next item starting with that character |
116
116
 
117
117
  ## WAI-ARIA roles and attributes
@@ -301,50 +301,51 @@ const Component = () => {
301
301
  isOpen={isModalOpen}
302
302
  onClose={handleClose}
303
303
  >
304
- <div className="n-flex n-justify-center">
305
- <FilledButton
306
- onClick={handleMenuClick}
307
- ref={anchorEl}
308
- aria-haspopup="menu"
309
- aria-expanded={isOpen}
310
- >
311
- Open Menu
312
- </FilledButton>
313
- </div>
314
- <Menu
315
- isOpen={isOpen}
316
- anchorRef={anchorEl}
317
- onClose={(event, _data) => {
318
- setIsOpen(false);
319
- event?.preventDefault();
320
- event?.stopPropagation();
321
- }}
322
- portalTarget={document.getElementById('modal-root')}
323
- htmlAttributes={{ id: 'dialog-menu' }}
324
- >
325
- <Menu.Item title="Undo" onClick={() => alert('Undo')} />
326
- <Menu.Item title="Redo" isDisabled />
327
- <Menu.Item title="Cut" description="Copy and remove" />
304
+ <Dialog.Header>Menu in Dialog</Dialog.Header>
305
+ <Dialog.Content>
306
+ <div className="n-flex n-justify-center">
307
+ <FilledButton
308
+ onClick={handleMenuClick}
309
+ ref={anchorEl}
310
+ aria-haspopup="menu"
311
+ aria-expanded={isOpen}
312
+ >
313
+ Open Menu
314
+ </FilledButton>
315
+ </div>
328
316
  <Menu
329
- title="Copy as"
330
- description="Copying as something"
331
- icon={<Square2StackIconOutline />}
317
+ isOpen={isOpen}
318
+ anchorRef={anchorEl}
319
+ onClose={(_event, _data) => {
320
+ setIsOpen(false);
321
+ }}
322
+ portalTarget={document.getElementById('modal-root')}
323
+ htmlAttributes={{ id: 'dialog-menu' }}
332
324
  >
333
- <Menu.Item title="Text" />
334
- <Menu.Item title="Video" />
335
- <Menu title="Image">
336
- <Menu.Item title=".png" />
337
- <Menu.Item title=".jpg" />
338
- <Menu.Item title=".svg" />
339
- <Menu.Item title=".gif" />
340
- </Menu>
341
- <Menu.Item title="Audio" />
342
- <Menu title="Share">
343
- <Menu.Item title="Mail" />
344
- <Menu.Item title="Instagram" />
325
+ <Menu.Item title="Undo" onClick={() => alert('Undo')} />
326
+ <Menu.Item title="Redo" isDisabled />
327
+ <Menu.Item title="Cut" description="Copy and remove" />
328
+ <Menu
329
+ title="Copy as"
330
+ description="Copying as something"
331
+ icon={<Square2StackIconOutline />}
332
+ >
333
+ <Menu.Item title="Text" />
334
+ <Menu.Item title="Video" />
335
+ <Menu title="Image">
336
+ <Menu.Item title=".png" />
337
+ <Menu.Item title=".jpg" />
338
+ <Menu.Item title=".svg" />
339
+ <Menu.Item title=".gif" />
340
+ </Menu>
341
+ <Menu.Item title="Audio" />
342
+ <Menu title="Share">
343
+ <Menu.Item title="Mail" />
344
+ <Menu.Item title="Instagram" />
345
+ </Menu>
345
346
  </Menu>
346
347
  </Menu>
347
- </Menu>
348
+ </Dialog.Content>
348
349
  </Dialog>
349
350
  </>
350
351
  );
@@ -109,6 +109,50 @@ const Component = () => {
109
109
  export default Component;
110
110
  ```
111
111
 
112
+ ### In Popover Dialog
113
+
114
+ ```tsx
115
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
116
+
117
+ import {
118
+ Dialog,
119
+ FilledButton,
120
+ type NeedleTime,
121
+ Popover,
122
+ TimePicker,
123
+ } from '@neo4j-ndl/react';
124
+ import { useState } from 'react';
125
+
126
+ const Component = () => {
127
+ const [selectedTime, setSelectedTime] = useState<NeedleTime>();
128
+
129
+ return (
130
+ <Dialog isOpen={true} aria-label="Dialog">
131
+ <Dialog.Header>
132
+ Using Time Picker inside a popover in a dialog
133
+ </Dialog.Header>
134
+ <Dialog.Description className="n-flex n-flex-col n-gap-token-32">
135
+ <Popover>
136
+ <Popover.Trigger hasButtonWrapper>
137
+ <FilledButton>Open Popover</FilledButton>
138
+ </Popover.Trigger>
139
+ <Popover.Content className="n-p-token-16">
140
+ <TimePicker
141
+ label="Select Time"
142
+ value={selectedTime}
143
+ onChange={(time) => setSelectedTime(time)}
144
+ htmlAttributes={{ id: 'time-picker-input' }}
145
+ />
146
+ </Popover.Content>
147
+ </Popover>
148
+ </Dialog.Description>
149
+ </Dialog>
150
+ );
151
+ };
152
+
153
+ export default Component;
154
+ ```
155
+
112
156
  ### With Seconds
113
157
 
114
158
  ```tsx
@@ -382,6 +382,49 @@ const Component = () => {
382
382
  export default Component;
383
383
  ```
384
384
 
385
+ ### In Popover Dialog
386
+
387
+ ```tsx
388
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
389
+
390
+ import {
391
+ Dialog,
392
+ FilledButton,
393
+ Popover,
394
+ TimeZonePicker,
395
+ } from '@neo4j-ndl/react';
396
+ import { useState } from 'react';
397
+
398
+ const Component = () => {
399
+ const [selectedTimeZone, setSelectedTimeZone] = useState<string>('UTC');
400
+
401
+ return (
402
+ <Dialog isOpen={true} aria-label="Dialog">
403
+ <Dialog.Header>
404
+ Using Timezone Picker inside a popover in a dialog
405
+ </Dialog.Header>
406
+ <Dialog.Description className="n-flex n-flex-col n-gap-token-32">
407
+ <Popover>
408
+ <Popover.Trigger hasButtonWrapper>
409
+ <FilledButton>Open Popover</FilledButton>
410
+ </Popover.Trigger>
411
+ <Popover.Content className="n-p-token-16">
412
+ <TimeZonePicker
413
+ label="Timezone"
414
+ value={selectedTimeZone}
415
+ onChange={setSelectedTimeZone}
416
+ htmlAttributes={{ id: 'time-zone-input' }}
417
+ />
418
+ </Popover.Content>
419
+ </Popover>
420
+ </Dialog.Description>
421
+ </Dialog>
422
+ );
423
+ };
424
+
425
+ export default Component;
426
+ ```
427
+
385
428
  ### Sizes
386
429
 
387
430
  ```tsx