@neo4j-ndl/react 4.16.8 → 4.16.9

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 (76) hide show
  1. package/package.json +5 -2
  2. package/skills/ndl-react/SKILL.md +152 -0
  3. package/skills/ndl-react/components/accordion.md +386 -0
  4. package/skills/ndl-react/components/ai/code-preview.md +128 -0
  5. package/skills/ndl-react/components/ai/file-tag.md +90 -0
  6. package/skills/ndl-react/components/ai/image-tag.md +91 -0
  7. package/skills/ndl-react/components/ai/more-files.md +73 -0
  8. package/skills/ndl-react/components/ai/presence.md +54 -0
  9. package/skills/ndl-react/components/ai/preview.md +498 -0
  10. package/skills/ndl-react/components/ai/prompt.md +362 -0
  11. package/skills/ndl-react/components/ai/reasoning.md +95 -0
  12. package/skills/ndl-react/components/ai/response.md +1109 -0
  13. package/skills/ndl-react/components/ai/suggestion.md +84 -0
  14. package/skills/ndl-react/components/ai/thinking.md +43 -0
  15. package/skills/ndl-react/components/ai/tool-call.md +43 -0
  16. package/skills/ndl-react/components/ai/user-bubble.md +187 -0
  17. package/skills/ndl-react/components/avatar.md +169 -0
  18. package/skills/ndl-react/components/banner.md +225 -0
  19. package/skills/ndl-react/components/box.md +39 -0
  20. package/skills/ndl-react/components/breadcrumbs.md +245 -0
  21. package/skills/ndl-react/components/checkbox.md +269 -0
  22. package/skills/ndl-react/components/clean-icon-button.md +294 -0
  23. package/skills/ndl-react/components/clipboard-button.md +154 -0
  24. package/skills/ndl-react/components/code-block.md +276 -0
  25. package/skills/ndl-react/components/code.md +68 -0
  26. package/skills/ndl-react/components/color-picker.md +131 -0
  27. package/skills/ndl-react/components/conditional-wrap.md +46 -0
  28. package/skills/ndl-react/components/data-grid.md +3121 -0
  29. package/skills/ndl-react/components/date-picker.md +652 -0
  30. package/skills/ndl-react/components/dialog.md +485 -0
  31. package/skills/ndl-react/components/dismissible-tag.md +136 -0
  32. package/skills/ndl-react/components/divider.md +96 -0
  33. package/skills/ndl-react/components/drawer.md +543 -0
  34. package/skills/ndl-react/components/dropdown-button.md +161 -0
  35. package/skills/ndl-react/components/dropzone.md +371 -0
  36. package/skills/ndl-react/components/filled-button.md +26 -0
  37. package/skills/ndl-react/components/flex.md +82 -0
  38. package/skills/ndl-react/components/graph-label.md +167 -0
  39. package/skills/ndl-react/components/icon-button-array.md +187 -0
  40. package/skills/ndl-react/components/icon-button.md +193 -0
  41. package/skills/ndl-react/components/inline-edit.md +209 -0
  42. package/skills/ndl-react/components/kbd.md +63 -0
  43. package/skills/ndl-react/components/loading-bar.md +43 -0
  44. package/skills/ndl-react/components/loading-spinner.md +57 -0
  45. package/skills/ndl-react/components/logo.md +57 -0
  46. package/skills/ndl-react/components/menu.md +993 -0
  47. package/skills/ndl-react/components/modal.md +27 -0
  48. package/skills/ndl-react/components/next/tree-view.md +966 -0
  49. package/skills/ndl-react/components/outlined-button.md +26 -0
  50. package/skills/ndl-react/components/popover.md +283 -0
  51. package/skills/ndl-react/components/progress-bar.md +70 -0
  52. package/skills/ndl-react/components/radio.md +150 -0
  53. package/skills/ndl-react/components/read-only-tag.md +96 -0
  54. package/skills/ndl-react/components/segmented-control.md +200 -0
  55. package/skills/ndl-react/components/select-icon-button.md +183 -0
  56. package/skills/ndl-react/components/select.md +530 -0
  57. package/skills/ndl-react/components/selectable-tag.md +203 -0
  58. package/skills/ndl-react/components/side-navigation.md +652 -0
  59. package/skills/ndl-react/components/skeleton.md +274 -0
  60. package/skills/ndl-react/components/slider.md +308 -0
  61. package/skills/ndl-react/components/spotlight.md +796 -0
  62. package/skills/ndl-react/components/status-indicator.md +57 -0
  63. package/skills/ndl-react/components/status-label.md +132 -0
  64. package/skills/ndl-react/components/switch.md +167 -0
  65. package/skills/ndl-react/components/tabs.md +433 -0
  66. package/skills/ndl-react/components/tag.md +91 -0
  67. package/skills/ndl-react/components/text-area.md +178 -0
  68. package/skills/ndl-react/components/text-button.md +25 -0
  69. package/skills/ndl-react/components/text-input.md +475 -0
  70. package/skills/ndl-react/components/text-link.md +119 -0
  71. package/skills/ndl-react/components/time-picker.md +137 -0
  72. package/skills/ndl-react/components/timezone-picker.md +496 -0
  73. package/skills/ndl-react/components/tooltip.md +478 -0
  74. package/skills/ndl-react/components/tree-view.md +545 -0
  75. package/skills/ndl-react/components/typography.md +72 -0
  76. package/skills/ndl-react/components/wizard.md +152 -0
@@ -0,0 +1,796 @@
1
+ # Spotlight
2
+
3
+ Import: `import { Spotlight } from '@neo4j-ndl/react'`
4
+
5
+ ## Props
6
+
7
+ ### Spotlight
8
+
9
+ | Prop | Type | Required | Default | Description |
10
+ |------|------|----------|---------|-------------|
11
+ | `actions` | `ReactNode` | | | The actions to be displayed in the Spotlight. Should only be TextButton or OutlinedButton components. |
12
+ | `beforeActions` | `ReactNode` | | | A ReactNode that can be put in the left corner of the Spotlight (left of action buttons). It should be used to display the current step if you have a multi-step tour |
13
+ | `children` | `ReactNode` | | | Children should be Spotlight subcomponents |
14
+ | `closeOnClickOutside` | `boolean` | | `false` | If the popover should close when the user clicks outside of it |
15
+ | `initialFocus` | `number \| RefObject<HTMLElement \| null>` | | | Which element to initially focus. * |
16
+ | `onClose` | `((action: SpotlightCloseAction) => void)` | | | A callback function that is called if the Spotlight is closed by either clicking outside the Spotlight, or by pressing the Escape key. The function has one argument: action (string that can be either "clickOutside" or "escapeKeyDown") |
17
+ | `onOpen` | `(() => void)` | | | Callback function called when the spotlight is opened |
18
+ | `placement` | `'bottom-end-bottom-start' \| 'bottom-end-top-end' \| 'bottom-middle-top-middle' \| 'bottom-start-bottom-end' \| 'bottom-start-top-start' \| 'middle-end-middle-start' \| 'middle-start-middle-end' \| 'top-end-bottom-end' \| 'top-end-top-start' \| 'top-middle-bottom-middle' \| 'top-start-bottom-start' \| 'top-start-top-end'` | | | The placement of the floating element is determined by two sets of words. The first set of words specifies the point on the anchor element where the floating element will be attached. The second set of coordinates specifies the point on the floating element that will attach to the anchor element. |
19
+ | `ref` | `Ref<HTMLDivElement>` | | | A ref to apply to the root element. |
20
+ | `target` | `string` | ✅ | | The id of the `SpotlightTarget` that this `Spotlight` should be rendered next to |
21
+
22
+ ### Spotlight.Body
23
+
24
+ | Prop | Type | Required | Default | Description |
25
+ |------|------|----------|---------|-------------|
26
+ | `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
27
+ | `children` | `ReactNode` | | | The spotlight body content |
28
+ | `ref` | `any` | | | A ref to apply to the root element. |
29
+
30
+ ### Spotlight.Header
31
+
32
+ | Prop | Type | Required | Default | Description |
33
+ |------|------|----------|---------|-------------|
34
+ | `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
35
+ | `children` | `ReactNode` | | | The spotlight header content |
36
+ | `ref` | `any` | | | A ref to apply to the root element. |
37
+
38
+ ### Spotlight.IconWrapper
39
+
40
+ | Prop | Type | Required | Default | Description |
41
+ |------|------|----------|---------|-------------|
42
+ | `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
43
+ | `children` | `ReactNode` | | | Content displayed in the icon wrapper |
44
+ | `ref` | `any` | | | A ref to apply to the root element. |
45
+
46
+ ### Spotlight.Image
47
+
48
+ | Prop | Type | Required | Default | Description |
49
+ |------|------|----------|---------|-------------|
50
+ | `alt` | `string` | ✅ | | A string that represents the alt text of the image |
51
+ | `ref` | `Ref<HTMLImageElement>` | | | A ref to apply to the root element. |
52
+ | `src` | `string` | ✅ | | A string that represents the URL of the image |
53
+
54
+ ### Spotlight.Label
55
+
56
+ | Prop | Type | Required | Default | Description |
57
+ |------|------|----------|---------|-------------|
58
+ | `as` | `("symbol" & ElementType<any, keyof IntrinsicElements>) \| ("object" & ElementType<any, keyof IntrinsicElements>) \| ... 177 more ... \| (FunctionComponent<...> & ElementType<...>)` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
59
+ | `children` | `ReactNode` | ✅ | | The content displayed inside the status label |
60
+ | `hasIcon` | `boolean` | | | Whether the status label have an icon |
61
+ | `ref` | `any` | | | A ref to apply to the root element. |
62
+ | `size` | `'large' \| 'small'` | | | Size of the status label |
63
+ | `variant` | `'danger' \| 'default' \| 'discovery' \| 'info' \| 'success' \| 'warning'` | | | Color of the status label that indicates its purpose. |
64
+
65
+ ## Accessibility
66
+
67
+ ## Implementation guidelines
68
+
69
+ The Spotlight component follows WAI-ARIA dialog pattern guidelines. Includes features such as focus trapping, keyboard navigation support, and proper ARIA roles for enhanced accessibility.
70
+ Please note that you should always provide either a Spotlight.Header, aria-label or aria-labelledby.
71
+
72
+ ## Examples
73
+
74
+ ### Fixed Positioning
75
+
76
+ ```tsx
77
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
78
+
79
+ import {
80
+ FilledButton,
81
+ OutlinedButton,
82
+ Spotlight,
83
+ SpotlightTarget,
84
+ useNeedleTheme,
85
+ useSpotlightContext,
86
+ } from '@neo4j-ndl/react';
87
+ import { useEffect } from 'react';
88
+
89
+ const Component = (props: { isChromatic: boolean }) => {
90
+ const { themeClassName } = useNeedleTheme();
91
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
92
+
93
+ const targetId = `test-target-${themeClassName}`;
94
+
95
+ useEffect(() => {
96
+ if (props.isChromatic) {
97
+ setActiveSpotlight(targetId);
98
+ setIsOpen(true);
99
+ }
100
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
101
+
102
+ return (
103
+ <div className="n-flex n-justify-center n-gap-token-64 n-h-[100px]">
104
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
105
+ Activate Spotlight
106
+ </FilledButton>
107
+ <div className="n-left-[auto] n-top-[110px] n-fixed">
108
+ <SpotlightTarget
109
+ id={targetId}
110
+ hasPulse={!props.isChromatic}
111
+ asChild
112
+ indicatorVariant="border"
113
+ indicatorPlacement="middle-middle"
114
+ >
115
+ <FilledButton onClick={() => alert('Target button clicked')}>
116
+ Target
117
+ </FilledButton>
118
+ </SpotlightTarget>
119
+ </div>
120
+ <Spotlight
121
+ placement="bottom-end-top-end"
122
+ target={targetId}
123
+ actions={
124
+ <OutlinedButton
125
+ onClick={() => {
126
+ setIsOpen(false);
127
+ setActiveSpotlight(null);
128
+ }}
129
+ >
130
+ Close
131
+ </OutlinedButton>
132
+ }
133
+ >
134
+ <Spotlight.Header>This is a header</Spotlight.Header>
135
+ <Spotlight.Body>This is content</Spotlight.Body>
136
+ </Spotlight>
137
+ </div>
138
+ );
139
+ };
140
+
141
+ export default Component;
142
+ ```
143
+
144
+ ### In Dialog
145
+
146
+ ```tsx
147
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
148
+
149
+ import {
150
+ Dialog,
151
+ FilledButton,
152
+ OutlinedButton,
153
+ Spotlight,
154
+ SpotlightTarget,
155
+ Typography,
156
+ useNeedleTheme,
157
+ useSpotlightContext,
158
+ } from '@neo4j-ndl/react';
159
+ import { useEffect, useState } from 'react';
160
+
161
+ const Component = (props: { isChromatic: boolean }) => {
162
+ const { themeClassName } = useNeedleTheme();
163
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
164
+
165
+ const [isModalOpen, setIsModalOpen] = useState<boolean>(props.isChromatic);
166
+ const targetId = `test-target-${themeClassName}`;
167
+
168
+ useEffect(() => {
169
+ if (props.isChromatic && isModalOpen) {
170
+ setActiveSpotlight(targetId);
171
+ setIsOpen(true);
172
+ }
173
+ }, [isModalOpen, setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
174
+
175
+ return (
176
+ <div className="n-flex n-justify-center n-gap-token-64">
177
+ <FilledButton onClick={() => setIsModalOpen(true)}>
178
+ Open Dialog
179
+ </FilledButton>
180
+ <Dialog
181
+ isOpen={isModalOpen}
182
+ onClose={() => setIsModalOpen(false)}
183
+ className={themeClassName}
184
+ >
185
+ <Dialog.Header>Using Spotlight inside a dialog</Dialog.Header>
186
+ <Dialog.Content className="n-flex n-flex-col n-gap-token-32">
187
+ <Typography variant="body-medium">
188
+ Spotlight and SpotlightTarget should behave automatically correct
189
+ when used inside a dialog. If positioning is not on top of
190
+ everything, you might want to override the
191
+ <code>--spotlight-z-index</code> css variable.
192
+ </Typography>
193
+ <div className="n-flex n-justify-center n-gap-token-64">
194
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
195
+ Activate Spotlight
196
+ </FilledButton>
197
+ <SpotlightTarget
198
+ id={targetId}
199
+ hasPulse={!props.isChromatic}
200
+ asChild
201
+ indicatorVariant="border"
202
+ >
203
+ <FilledButton onClick={() => alert('Target button clicked')}>
204
+ Target
205
+ </FilledButton>
206
+ </SpotlightTarget>
207
+ </div>
208
+ </Dialog.Content>
209
+ <Spotlight
210
+ placement="bottom-end-top-end"
211
+ target={targetId}
212
+ actions={
213
+ <OutlinedButton
214
+ onClick={() => {
215
+ setIsOpen(false);
216
+ setActiveSpotlight(null);
217
+ }}
218
+ >
219
+ Close
220
+ </OutlinedButton>
221
+ }
222
+ >
223
+ <Spotlight.Header>This is a header</Spotlight.Header>
224
+ <Spotlight.Body>This is content</Spotlight.Body>
225
+ </Spotlight>
226
+ </Dialog>
227
+ </div>
228
+ );
229
+ };
230
+
231
+ export default Component;
232
+ ```
233
+
234
+ ### In Side Nav
235
+
236
+ ```tsx
237
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
238
+
239
+ import {
240
+ FilledButton,
241
+ OutlinedButton,
242
+ SideNavigation,
243
+ Spotlight,
244
+ SpotlightTarget,
245
+ useNeedleTheme,
246
+ useSpotlightContext,
247
+ } from '@neo4j-ndl/react';
248
+ import { useEffect, useState } from 'react';
249
+
250
+ const Component = (props: { isChromatic: boolean }) => {
251
+ const { themeClassName } = useNeedleTheme();
252
+ const { setActiveSpotlight, setIsOpen } = useSpotlightContext();
253
+
254
+ const [isSelected, setIsSelected] = useState<string | null>(
255
+ 'aura-db-instances',
256
+ );
257
+ const targetId = `test-target-${themeClassName}`;
258
+
259
+ const handleClick = (item: string) => {
260
+ setIsSelected(item);
261
+ };
262
+
263
+ useEffect(() => {
264
+ if (props.isChromatic) {
265
+ setActiveSpotlight(targetId);
266
+ setIsOpen(true);
267
+ }
268
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
269
+
270
+ return (
271
+ <div className="n-h-[500px] n-flex">
272
+ <SideNavigation isExpanded={true} ariaLabel="Main side navigation">
273
+ <SideNavigation.CategoryHeader>AuraDB</SideNavigation.CategoryHeader>
274
+ <SideNavigation.ListItem>
275
+ <SideNavigation.NavItem
276
+ onClick={() => handleClick('aura-db-instances')}
277
+ isActive={isSelected === 'aura-db-instances'}
278
+ label="Instances"
279
+ />
280
+ </SideNavigation.ListItem>
281
+ <SideNavigation.ListItem>
282
+ <SideNavigation.NavItem
283
+ onClick={() => handleClick('aura-db-connect')}
284
+ isActive={isSelected === 'aura-db-connect'}
285
+ label="Connect"
286
+ />
287
+ </SideNavigation.ListItem>
288
+ <SideNavigation.ListItem>
289
+ <SideNavigation.NavItem
290
+ onClick={() => handleClick('aura-db-python')}
291
+ isActive={isSelected === 'aura-db-python'}
292
+ label="Python"
293
+ />
294
+ </SideNavigation.ListItem>
295
+ <SideNavigation.ListItem>
296
+ <SpotlightTarget
297
+ id={targetId}
298
+ hasPulse={!props.isChromatic}
299
+ borderRadius={4}
300
+ indicatorVariant="point"
301
+ indicatorPlacement="top-right"
302
+ asChild
303
+ >
304
+ <SideNavigation.NavItem
305
+ onClick={() => handleClick('aura-db-javascript')}
306
+ isActive={isSelected === 'aura-db-javascript'}
307
+ label="JavaScript"
308
+ />
309
+ </SpotlightTarget>
310
+ </SideNavigation.ListItem>
311
+ <SideNavigation.CategoryHeader>AuraDS</SideNavigation.CategoryHeader>
312
+ <SideNavigation.ListItem>
313
+ <SideNavigation.NavItem
314
+ onClick={() => handleClick('aura-ds-instances')}
315
+ isActive={isSelected === 'aura-ds-instances'}
316
+ label="Instances"
317
+ />
318
+ </SideNavigation.ListItem>
319
+ <SideNavigation.ListItem>
320
+ <SideNavigation.NavItem
321
+ onClick={() => handleClick('aura-ds-getting-started')}
322
+ isActive={isSelected === 'aura-ds-getting-started'}
323
+ label="Getting Started"
324
+ />
325
+ </SideNavigation.ListItem>
326
+ </SideNavigation>
327
+ <div className="n-w-full n-h-full n-flex n-flex-col n-items-center n-justify-center n-rounded-md n-p-token-16">
328
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
329
+ Activate Spotlight
330
+ </FilledButton>
331
+ </div>
332
+ <Spotlight
333
+ placement="top-end-top-start"
334
+ target={targetId}
335
+ actions={
336
+ <OutlinedButton
337
+ onClick={() => {
338
+ setIsOpen(false);
339
+ setActiveSpotlight(null);
340
+ }}
341
+ >
342
+ Close
343
+ </OutlinedButton>
344
+ }
345
+ >
346
+ <Spotlight.Header>This is a header</Spotlight.Header>
347
+ <Spotlight.Body>This is content</Spotlight.Body>
348
+ </Spotlight>
349
+ </div>
350
+ );
351
+ };
352
+
353
+ export default Component;
354
+ ```
355
+
356
+ ### On Tabs
357
+
358
+ ```tsx
359
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
360
+
361
+ import {
362
+ FilledButton,
363
+ OutlinedButton,
364
+ Spotlight,
365
+ SpotlightTarget,
366
+ Tabs,
367
+ Typography,
368
+ useNeedleTheme,
369
+ useSpotlightContext,
370
+ } from '@neo4j-ndl/react';
371
+ import { useState } from 'react';
372
+
373
+ const Component = ({ hasPulse = true }: { hasPulse?: boolean }) => {
374
+ const { themeClassName } = useNeedleTheme();
375
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
376
+ const [tabsValue, setTabsValue] = useState('0');
377
+
378
+ const targetId = `test-target-${themeClassName}`;
379
+
380
+ return (
381
+ <div className="n-flex n-justify-center n-gap-token-10">
382
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
383
+ Activate Spotlight
384
+ </FilledButton>
385
+ <div>
386
+ <Tabs value={tabsValue} onChange={setTabsValue}>
387
+ <SpotlightTarget
388
+ id={targetId}
389
+ hasPulse={hasPulse}
390
+ borderRadius={4}
391
+ indicatorVariant="point"
392
+ >
393
+ <Tabs.Tab id="0">Tab 1</Tabs.Tab>
394
+ </SpotlightTarget>
395
+ <Tabs.Tab id="1">Tab 2</Tabs.Tab>
396
+ <Tabs.Tab id="2">Tab 3</Tabs.Tab>
397
+ </Tabs>
398
+ <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="0">
399
+ <Typography variant="body-medium">Tab 1 content</Typography>
400
+ </Tabs.TabPanel>
401
+ <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="1">
402
+ <Typography variant="body-medium">Tab 2 content</Typography>
403
+ </Tabs.TabPanel>
404
+ <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="2">
405
+ <Typography variant="body-medium">Tab 3 content</Typography>
406
+ </Tabs.TabPanel>
407
+ </div>
408
+ <Spotlight
409
+ placement="bottom-end-top-end"
410
+ target={targetId}
411
+ actions={
412
+ <OutlinedButton
413
+ onClick={() => {
414
+ setIsOpen(false);
415
+ setActiveSpotlight(null);
416
+ }}
417
+ >
418
+ Close
419
+ </OutlinedButton>
420
+ }
421
+ >
422
+ <Spotlight.Header>This is a header</Spotlight.Header>
423
+ <Spotlight.Body>This is content</Spotlight.Body>
424
+ </Spotlight>
425
+ </div>
426
+ );
427
+ };
428
+
429
+ export default Component;
430
+ ```
431
+
432
+ ### Tour
433
+
434
+ ```tsx
435
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
436
+
437
+ import {
438
+ FilledButton,
439
+ OutlinedButton,
440
+ Spotlight,
441
+ SpotlightTarget,
442
+ SpotlightTour,
443
+ useNeedleTheme,
444
+ useSpotlightContext,
445
+ } from '@neo4j-ndl/react';
446
+ import { FingerPrintIconOutline } from '@neo4j-ndl/react/icons';
447
+
448
+ const Component = () => {
449
+ const { themeClassName } = useNeedleTheme();
450
+ const { setActiveSpotlight } = useSpotlightContext();
451
+
452
+ return (
453
+ <div className="n-flex n-justify-center n-gap-token-64">
454
+ <OutlinedButton
455
+ onClick={() => setActiveSpotlight(`test-target-1-${themeClassName}`)}
456
+ >
457
+ Start tour
458
+ </OutlinedButton>
459
+ <SpotlightTarget id={`test-target-1-${themeClassName}`} hasPulse asChild>
460
+ <FilledButton onClick={() => alert('Target 1 clicked')}>
461
+ Target 1
462
+ </FilledButton>
463
+ </SpotlightTarget>
464
+ <SpotlightTarget id={`test-target-2-${themeClassName}`} hasPulse asChild>
465
+ <FilledButton onClick={() => alert('Target 2 clicked')}>
466
+ Target 2
467
+ </FilledButton>
468
+ </SpotlightTarget>
469
+ <SpotlightTarget id={`test-target-3-${themeClassName}`} hasPulse asChild>
470
+ <FilledButton onClick={() => alert('Target 3 clicked')}>
471
+ Target 3
472
+ </FilledButton>
473
+ </SpotlightTarget>
474
+ <SpotlightTour
475
+ onAction={(target, action) =>
476
+ console.info(`Action ${action} was performed in spotlight ${target}`)
477
+ }
478
+ spotlights={[
479
+ {
480
+ children: (
481
+ <>
482
+ <Spotlight.Label>NEW</Spotlight.Label>
483
+ <Spotlight.Header>This is a header</Spotlight.Header>
484
+ <Spotlight.Body>This is content</Spotlight.Body>
485
+ </>
486
+ ),
487
+ target: `test-target-1-${themeClassName}`,
488
+ },
489
+ {
490
+ children: (
491
+ <>
492
+ <Spotlight.IconWrapper>
493
+ <FingerPrintIconOutline />
494
+ </Spotlight.IconWrapper>
495
+ <Spotlight.Header>This is a header</Spotlight.Header>
496
+ <Spotlight.Body>This is content</Spotlight.Body>
497
+ </>
498
+ ),
499
+ target: `test-target-2-${themeClassName}`,
500
+ },
501
+ {
502
+ children: (
503
+ <>
504
+ <Spotlight.Image
505
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjY2NjIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkV4YW1wbGUgSW1hZ2U8L3RleHQ+PC9zdmc+"
506
+ alt="example image"
507
+ />
508
+ <Spotlight.Body>This is content</Spotlight.Body>
509
+ </>
510
+ ),
511
+ target: `test-target-3-${themeClassName}`,
512
+ },
513
+ ]}
514
+ />
515
+ </div>
516
+ );
517
+ };
518
+
519
+ export default Component;
520
+ ```
521
+
522
+ ### With Icon
523
+
524
+ ```tsx
525
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
526
+
527
+ import {
528
+ FilledButton,
529
+ OutlinedButton,
530
+ Spotlight,
531
+ SpotlightTarget,
532
+ TextButton,
533
+ useNeedleTheme,
534
+ useSpotlightContext,
535
+ } from '@neo4j-ndl/react';
536
+ import { FingerPrintIconOutline } from '@neo4j-ndl/react/icons';
537
+ import { useEffect } from 'react';
538
+
539
+ const Component = (props: { isChromatic: boolean }) => {
540
+ const { themeClassName } = useNeedleTheme();
541
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
542
+
543
+ const targetId = `test-target-${themeClassName}`;
544
+
545
+ useEffect(() => {
546
+ if (props.isChromatic) {
547
+ setActiveSpotlight(targetId);
548
+ setIsOpen(true);
549
+ }
550
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
551
+
552
+ return (
553
+ <div className="n-flex n-justify-center n-gap-token-64">
554
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
555
+ Activate Spotlight
556
+ </FilledButton>
557
+ <SpotlightTarget
558
+ id={targetId}
559
+ hasPulse={!props.isChromatic}
560
+ indicatorVariant="border"
561
+ asChild
562
+ >
563
+ <TextButton onClick={() => alert('Target button clicked')}>
564
+ Target
565
+ </TextButton>
566
+ </SpotlightTarget>
567
+ <Spotlight
568
+ placement="bottom-end-top-end"
569
+ target={targetId}
570
+ actions={
571
+ <OutlinedButton
572
+ onClick={() => {
573
+ setIsOpen(false);
574
+ setActiveSpotlight(null);
575
+ }}
576
+ >
577
+ Close
578
+ </OutlinedButton>
579
+ }
580
+ >
581
+ <Spotlight.IconWrapper>
582
+ <FingerPrintIconOutline />
583
+ </Spotlight.IconWrapper>
584
+ <Spotlight.Header>This is a header</Spotlight.Header>
585
+ <Spotlight.Body>This is content</Spotlight.Body>
586
+ </Spotlight>
587
+ </div>
588
+ );
589
+ };
590
+
591
+ export default Component;
592
+ ```
593
+
594
+ ### With Image
595
+
596
+ ```tsx
597
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
598
+
599
+ import {
600
+ FilledButton,
601
+ OutlinedButton,
602
+ Spotlight,
603
+ SpotlightTarget,
604
+ TextButton,
605
+ useNeedleTheme,
606
+ useSpotlightContext,
607
+ } from '@neo4j-ndl/react';
608
+ import { useEffect } from 'react';
609
+
610
+ const Component = (props: { isChromatic: boolean }) => {
611
+ const { themeClassName } = useNeedleTheme();
612
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
613
+
614
+ const targetId = `test-target-${themeClassName}`;
615
+
616
+ useEffect(() => {
617
+ if (props.isChromatic) {
618
+ setActiveSpotlight(targetId);
619
+ setIsOpen(true);
620
+ }
621
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
622
+
623
+ return (
624
+ <div className="n-flex n-justify-center n-gap-token-64">
625
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
626
+ Activate Spotlight
627
+ </FilledButton>
628
+ <SpotlightTarget id={targetId} hasPulse={!props.isChromatic} asChild>
629
+ <TextButton onClick={() => alert('Target button clicked')}>
630
+ Target
631
+ </TextButton>
632
+ </SpotlightTarget>
633
+ <Spotlight
634
+ placement="bottom-end-top-end"
635
+ target={targetId}
636
+ actions={
637
+ <OutlinedButton
638
+ onClick={() => {
639
+ setIsOpen(false);
640
+ setActiveSpotlight(null);
641
+ }}
642
+ >
643
+ Close
644
+ </OutlinedButton>
645
+ }
646
+ >
647
+ <Spotlight.Image
648
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjY2NjIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkV4YW1wbGUgSW1hZ2U8L3RleHQ+PC9zdmc+"
649
+ alt="example image"
650
+ />
651
+ <Spotlight.Header>This is a header</Spotlight.Header>
652
+ <Spotlight.Body>This is content</Spotlight.Body>
653
+ </Spotlight>
654
+ </div>
655
+ );
656
+ };
657
+
658
+ export default Component;
659
+ ```
660
+
661
+ ### With Label
662
+
663
+ ```tsx
664
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
665
+
666
+ import {
667
+ FilledButton,
668
+ OutlinedButton,
669
+ Spotlight,
670
+ SpotlightTarget,
671
+ TextButton,
672
+ useNeedleTheme,
673
+ useSpotlightContext,
674
+ } from '@neo4j-ndl/react';
675
+ import { useEffect } from 'react';
676
+
677
+ const Component = (props: { isChromatic: boolean }) => {
678
+ const { themeClassName } = useNeedleTheme();
679
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
680
+
681
+ const targetId = `test-target-${themeClassName}`;
682
+
683
+ useEffect(() => {
684
+ if (props.isChromatic) {
685
+ setActiveSpotlight(targetId);
686
+ setIsOpen(true);
687
+ }
688
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
689
+
690
+ return (
691
+ <div className="n-flex n-justify-center n-gap-token-64">
692
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
693
+ Activate Spotlight
694
+ </FilledButton>
695
+ <SpotlightTarget
696
+ id={targetId}
697
+ hasPulse={!props.isChromatic}
698
+ indicatorVariant="border"
699
+ asChild
700
+ >
701
+ <TextButton onClick={() => alert('Target button clicked')}>
702
+ Target
703
+ </TextButton>
704
+ </SpotlightTarget>
705
+ <Spotlight
706
+ placement="bottom-end-top-end"
707
+ target={targetId}
708
+ actions={
709
+ <OutlinedButton
710
+ onClick={() => {
711
+ setIsOpen(false);
712
+ setActiveSpotlight(null);
713
+ }}
714
+ >
715
+ Close
716
+ </OutlinedButton>
717
+ }
718
+ >
719
+ <Spotlight.Label>NEW</Spotlight.Label>
720
+ <Spotlight.Header>This is a header</Spotlight.Header>
721
+ <Spotlight.Body>This is content</Spotlight.Body>
722
+ </Spotlight>
723
+ </div>
724
+ );
725
+ };
726
+
727
+ export default Component;
728
+ ```
729
+
730
+ ### With Pointer
731
+
732
+ ```tsx
733
+ import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
734
+
735
+ import {
736
+ FilledButton,
737
+ OutlinedButton,
738
+ Spotlight,
739
+ SpotlightTarget,
740
+ useNeedleTheme,
741
+ useSpotlightContext,
742
+ } from '@neo4j-ndl/react';
743
+ import { useEffect } from 'react';
744
+
745
+ const Component = (props: { isChromatic: boolean }) => {
746
+ const { themeClassName } = useNeedleTheme();
747
+ const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
748
+
749
+ const targetId = `test-target-${themeClassName}`;
750
+
751
+ useEffect(() => {
752
+ if (props.isChromatic) {
753
+ setActiveSpotlight(targetId);
754
+ setIsOpen(true);
755
+ }
756
+ }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);
757
+
758
+ return (
759
+ <div className="n-flex n-justify-center n-gap-token-64">
760
+ <FilledButton onClick={() => setActiveSpotlight(targetId)}>
761
+ Activate Spotlight
762
+ </FilledButton>
763
+ <SpotlightTarget
764
+ id={targetId}
765
+ hasPulse={!props.isChromatic}
766
+ asChild
767
+ indicatorVariant="point"
768
+ indicatorPlacement="top-right"
769
+ >
770
+ <FilledButton onClick={() => alert('Target button clicked')}>
771
+ Target
772
+ </FilledButton>
773
+ </SpotlightTarget>
774
+ <Spotlight
775
+ placement="bottom-end-top-end"
776
+ target={targetId}
777
+ actions={
778
+ <OutlinedButton
779
+ onClick={() => {
780
+ setIsOpen(false);
781
+ setActiveSpotlight(null);
782
+ }}
783
+ >
784
+ Close
785
+ </OutlinedButton>
786
+ }
787
+ >
788
+ <Spotlight.Header>This is a header</Spotlight.Header>
789
+ <Spotlight.Body>This is content</Spotlight.Body>
790
+ </Spotlight>
791
+ </div>
792
+ );
793
+ };
794
+
795
+ export default Component;
796
+ ```