# Spotlight

Import: `import { Spotlight } from '@neo4j-ndl/react'`

## Props

### Spotlight

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `actions` | `ReactNode` |  |  | The actions to be displayed in the Spotlight. Should only be TextButton or OutlinedButton components. |
| `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 |
| `children` | `ReactNode` |  |  | Children should be Spotlight subcomponents |
| `closeOnClickOutside` | `boolean` |  | `false` | If the popover should close when the user clicks outside of it |
| `initialFocus` | `number \| RefObject<HTMLElement \| null>` |  |  | Which element to initially focus. * |
| `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") |
| `onOpen` | `(() => void)` |  |  | Callback function called when the spotlight is opened |
| `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. |
| `ref` | `Ref<HTMLDivElement>` |  |  | A ref to apply to the root element. |
| `target` | `string` | ✅ |  | The id of the `SpotlightTarget` that this `Spotlight` should be rendered next to |

### Spotlight.Body

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` |  |  | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` |  |  | The spotlight body content |
| `ref` | `any` |  |  | A ref to apply to the root element. |

### Spotlight.Header

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` |  |  | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` |  |  | The spotlight header content |
| `ref` | `any` |  |  | A ref to apply to the root element. |

### Spotlight.IconWrapper

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` |  |  | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` |  |  | Content displayed in the icon wrapper |
| `ref` | `any` |  |  | A ref to apply to the root element. |

### Spotlight.Image

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `alt` | `string` | ✅ |  | A string that represents the alt text of the image |
| `ref` | `Ref<HTMLImageElement>` |  |  | A ref to apply to the root element. |
| `src` | `string` | ✅ |  | A string that represents the URL of the image |

### Spotlight.Label

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `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. |
| `children` | `ReactNode` | ✅ |  | The content displayed inside the status label |
| `hasIcon` | `boolean` |  |  | Whether the status label have an icon |
| `ref` | `any` |  |  | A ref to apply to the root element. |
| `size` | `'large' \| 'small'` |  |  | Size of the status label |
| `variant` | `'danger' \| 'default' \| 'discovery' \| 'info' \| 'success' \| 'warning'` |  |  | Color of the status label that indicates its purpose. |

## Accessibility

## Implementation guidelines

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.
Please note that you should always provide either a Spotlight.Header, aria-label or aria-labelledby.

## Examples

### Fixed Positioning

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64 n-h-[100px]">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <div className="n-left-[auto] n-top-[110px] n-fixed">
        <SpotlightTarget
          id={targetId}
          hasPulse={!props.isChromatic}
          asChild
          indicatorVariant="border"
          indicatorPlacement="middle-middle"
        >
          <FilledButton onClick={() => alert('Target button clicked')}>
            Target
          </FilledButton>
        </SpotlightTarget>
      </div>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### In Dialog

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  Dialog,
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  Typography,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect, useState } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const [isModalOpen, setIsModalOpen] = useState<boolean>(props.isChromatic);
  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic && isModalOpen) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [isModalOpen, setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <FilledButton onClick={() => setIsModalOpen(true)}>
        Open Dialog
      </FilledButton>
      <Dialog
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        className={themeClassName}
      >
        <Dialog.Header>Using Spotlight inside a dialog</Dialog.Header>
        <Dialog.Content className="n-flex n-flex-col n-gap-token-32">
          <Typography variant="body-medium">
            Spotlight and SpotlightTarget should behave automatically correct
            when used inside a dialog. If positioning is not on top of
            everything, you might want to override the
            <code>--spotlight-z-index</code> css variable.
          </Typography>
          <div className="n-flex n-justify-center n-gap-token-64">
            <FilledButton onClick={() => setActiveSpotlight(targetId)}>
              Activate Spotlight
            </FilledButton>
            <SpotlightTarget
              id={targetId}
              hasPulse={!props.isChromatic}
              asChild
              indicatorVariant="border"
            >
              <FilledButton onClick={() => alert('Target button clicked')}>
                Target
              </FilledButton>
            </SpotlightTarget>
          </div>
        </Dialog.Content>
        <Spotlight
          placement="bottom-end-top-end"
          target={targetId}
          actions={
            <OutlinedButton
              onClick={() => {
                setIsOpen(false);
                setActiveSpotlight(null);
              }}
            >
              Close
            </OutlinedButton>
          }
        >
          <Spotlight.Header>This is a header</Spotlight.Header>
          <Spotlight.Body>This is content</Spotlight.Body>
        </Spotlight>
      </Dialog>
    </div>
  );
};

export default Component;
```

### In Side Nav

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  SideNavigation,
  Spotlight,
  SpotlightTarget,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect, useState } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setActiveSpotlight, setIsOpen } = useSpotlightContext();

  const [isSelected, setIsSelected] = useState<string | null>(
    'aura-db-instances',
  );
  const targetId = `test-target-${themeClassName}`;

  const handleClick = (item: string) => {
    setIsSelected(item);
  };

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-h-[500px] n-flex">
      <SideNavigation isExpanded={true} ariaLabel="Main side navigation">
        <SideNavigation.CategoryHeader>AuraDB</SideNavigation.CategoryHeader>
        <SideNavigation.ListItem>
          <SideNavigation.NavItem
            onClick={() => handleClick('aura-db-instances')}
            isActive={isSelected === 'aura-db-instances'}
            label="Instances"
          />
        </SideNavigation.ListItem>
        <SideNavigation.ListItem>
          <SideNavigation.NavItem
            onClick={() => handleClick('aura-db-connect')}
            isActive={isSelected === 'aura-db-connect'}
            label="Connect"
          />
        </SideNavigation.ListItem>
        <SideNavigation.ListItem>
          <SideNavigation.NavItem
            onClick={() => handleClick('aura-db-python')}
            isActive={isSelected === 'aura-db-python'}
            label="Python"
          />
        </SideNavigation.ListItem>
        <SideNavigation.ListItem>
          <SpotlightTarget
            id={targetId}
            hasPulse={!props.isChromatic}
            borderRadius={4}
            indicatorVariant="point"
            indicatorPlacement="top-right"
            asChild
          >
            <SideNavigation.NavItem
              onClick={() => handleClick('aura-db-javascript')}
              isActive={isSelected === 'aura-db-javascript'}
              label="JavaScript"
            />
          </SpotlightTarget>
        </SideNavigation.ListItem>
        <SideNavigation.CategoryHeader>AuraDS</SideNavigation.CategoryHeader>
        <SideNavigation.ListItem>
          <SideNavigation.NavItem
            onClick={() => handleClick('aura-ds-instances')}
            isActive={isSelected === 'aura-ds-instances'}
            label="Instances"
          />
        </SideNavigation.ListItem>
        <SideNavigation.ListItem>
          <SideNavigation.NavItem
            onClick={() => handleClick('aura-ds-getting-started')}
            isActive={isSelected === 'aura-ds-getting-started'}
            label="Getting Started"
          />
        </SideNavigation.ListItem>
      </SideNavigation>
      <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">
        <FilledButton onClick={() => setActiveSpotlight(targetId)}>
          Activate Spotlight
        </FilledButton>
      </div>
      <Spotlight
        placement="top-end-top-start"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### On Tabs

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  Tabs,
  Typography,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useState } from 'react';

const Component = ({ hasPulse = true }: { hasPulse?: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();
  const [tabsValue, setTabsValue] = useState('0');

  const targetId = `test-target-${themeClassName}`;

  return (
    <div className="n-flex n-justify-center n-gap-token-10">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <div>
        <Tabs value={tabsValue} onChange={setTabsValue}>
          <SpotlightTarget
            id={targetId}
            hasPulse={hasPulse}
            borderRadius={4}
            indicatorVariant="point"
          >
            <Tabs.Tab id="0">Tab 1</Tabs.Tab>
          </SpotlightTarget>
          <Tabs.Tab id="1">Tab 2</Tabs.Tab>
          <Tabs.Tab id="2">Tab 3</Tabs.Tab>
        </Tabs>
        <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="0">
          <Typography variant="body-medium">Tab 1 content</Typography>
        </Tabs.TabPanel>
        <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="1">
          <Typography variant="body-medium">Tab 2 content</Typography>
        </Tabs.TabPanel>
        <Tabs.TabPanel className="n-p-token-4" value={tabsValue} tabId="2">
          <Typography variant="body-medium">Tab 3 content</Typography>
        </Tabs.TabPanel>
      </div>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### Tour

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  SpotlightTour,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { FingerPrintIconOutline } from '@neo4j-ndl/react/icons';

const Component = () => {
  const { themeClassName } = useNeedleTheme();
  const { setActiveSpotlight } = useSpotlightContext();

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <OutlinedButton
        onClick={() => setActiveSpotlight(`test-target-1-${themeClassName}`)}
      >
        Start tour
      </OutlinedButton>
      <SpotlightTarget id={`test-target-1-${themeClassName}`} hasPulse asChild>
        <FilledButton onClick={() => alert('Target 1 clicked')}>
          Target 1
        </FilledButton>
      </SpotlightTarget>
      <SpotlightTarget id={`test-target-2-${themeClassName}`} hasPulse asChild>
        <FilledButton onClick={() => alert('Target 2 clicked')}>
          Target 2
        </FilledButton>
      </SpotlightTarget>
      <SpotlightTarget id={`test-target-3-${themeClassName}`} hasPulse asChild>
        <FilledButton onClick={() => alert('Target 3 clicked')}>
          Target 3
        </FilledButton>
      </SpotlightTarget>
      <SpotlightTour
        onAction={(target, action) =>
          console.info(`Action ${action} was performed in spotlight ${target}`)
        }
        spotlights={[
          {
            children: (
              <>
                <Spotlight.Label>NEW</Spotlight.Label>
                <Spotlight.Header>This is a header</Spotlight.Header>
                <Spotlight.Body>This is content</Spotlight.Body>
              </>
            ),
            target: `test-target-1-${themeClassName}`,
          },
          {
            children: (
              <>
                <Spotlight.IconWrapper>
                  <FingerPrintIconOutline />
                </Spotlight.IconWrapper>
                <Spotlight.Header>This is a header</Spotlight.Header>
                <Spotlight.Body>This is content</Spotlight.Body>
              </>
            ),
            target: `test-target-2-${themeClassName}`,
          },
          {
            children: (
              <>
                <Spotlight.Image
                  src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjY2NjIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkV4YW1wbGUgSW1hZ2U8L3RleHQ+PC9zdmc+"
                  alt="example image"
                />
                <Spotlight.Body>This is content</Spotlight.Body>
              </>
            ),
            target: `test-target-3-${themeClassName}`,
          },
        ]}
      />
    </div>
  );
};

export default Component;
```

### With Icon

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  TextButton,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { FingerPrintIconOutline } from '@neo4j-ndl/react/icons';
import { useEffect } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <SpotlightTarget
        id={targetId}
        hasPulse={!props.isChromatic}
        indicatorVariant="border"
        asChild
      >
        <TextButton onClick={() => alert('Target button clicked')}>
          Target
        </TextButton>
      </SpotlightTarget>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.IconWrapper>
          <FingerPrintIconOutline />
        </Spotlight.IconWrapper>
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### With Image

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  TextButton,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <SpotlightTarget id={targetId} hasPulse={!props.isChromatic} asChild>
        <TextButton onClick={() => alert('Target button clicked')}>
          Target
        </TextButton>
      </SpotlightTarget>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Image
          src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjY2NjIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPkV4YW1wbGUgSW1hZ2U8L3RleHQ+PC9zdmc+"
          alt="example image"
        />
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### With Label

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  TextButton,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <SpotlightTarget
        id={targetId}
        hasPulse={!props.isChromatic}
        indicatorVariant="border"
        asChild
      >
        <TextButton onClick={() => alert('Target button clicked')}>
          Target
        </TextButton>
      </SpotlightTarget>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Label>NEW</Spotlight.Label>
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```

### With Pointer

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import {
  FilledButton,
  OutlinedButton,
  Spotlight,
  SpotlightTarget,
  useNeedleTheme,
  useSpotlightContext,
} from '@neo4j-ndl/react';
import { useEffect } from 'react';

const Component = (props: { isChromatic: boolean }) => {
  const { themeClassName } = useNeedleTheme();
  const { setIsOpen, setActiveSpotlight } = useSpotlightContext();

  const targetId = `test-target-${themeClassName}`;

  useEffect(() => {
    if (props.isChromatic) {
      setActiveSpotlight(targetId);
      setIsOpen(true);
    }
  }, [setActiveSpotlight, setIsOpen, targetId, props.isChromatic]);

  return (
    <div className="n-flex n-justify-center n-gap-token-64">
      <FilledButton onClick={() => setActiveSpotlight(targetId)}>
        Activate Spotlight
      </FilledButton>
      <SpotlightTarget
        id={targetId}
        hasPulse={!props.isChromatic}
        asChild
        indicatorVariant="point"
        indicatorPlacement="top-right"
      >
        <FilledButton onClick={() => alert('Target button clicked')}>
          Target
        </FilledButton>
      </SpotlightTarget>
      <Spotlight
        placement="bottom-end-top-end"
        target={targetId}
        actions={
          <OutlinedButton
            onClick={() => {
              setIsOpen(false);
              setActiveSpotlight(null);
            }}
          >
            Close
          </OutlinedButton>
        }
      >
        <Spotlight.Header>This is a header</Spotlight.Header>
        <Spotlight.Body>This is content</Spotlight.Body>
      </Spotlight>
    </div>
  );
};

export default Component;
```
