> ## Documentation Index
> Fetch the complete documentation index at: https://velt.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SpreadJS Setup

> Add Velt comments to a SpreadJS workbook with the Velt SpreadJS comments extension.

![Add text comments in a spreadsheet](https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/Add-Text-Comments.gif?s=1da499b73486c2acd4667b517baab389)

The SpreadJS integration renders each Velt comment as a view-only overlay positioned over the commented cell or range. It does not modify your workbook. Comment anchors are stored as durable `{ sheetName, row, col, rowCount, colCount }` data and re-resolved to pixels with SpreadJS cell geometry whenever comments render.

## Setup

#### Step 1: Add Comment components

* Add the `Velt Comments` component to the root of your app. This component is required to create and render comments in your app.
* Authenticate the user with `authProvider` and set the Velt document before users add comments.
* Set the `textMode` prop to `false` to hide the default Velt text comment tool. SpreadJS selections are handled by `@veltdev/spreadjs-velt-comments`.
* Add `VeltCommentsSidebar` if you want a Google Docs-style comment sidebar.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { VeltComments, VeltCommentsSidebar, VeltProvider, useSetDocument } from '@veltdev/react';
>
> const user = {
>   userId: 'user-1',
>   organizationId: 'org-1',
>   name: 'User One',
>   email: 'user@example.com',
> };
>
> function VeltSetup() {
>   useSetDocument('spreadsheet-id', { documentName: 'Spreadsheet name' });
>   return null;
> }
>
> function App() {
>   return (
>     <VeltProvider apiKey="API_KEY" authProvider={{ user }}>
>       <VeltSetup />
>       <VeltComments textMode={false} />
>       <VeltCommentsSidebar />
>       {/* Your app content */}
>     </VeltProvider>
>   );
> }
> ```

#### Step 2: Install the Velt SpreadJS extension

```bash theme={null}
npm i @veltdev/spreadjs-velt-comments @mescius/spread-sheets @mescius/spread-sheets-io
```

`@mescius/spread-sheets` is a peer dependency of the Velt SpreadJS package. `@mescius/spread-sheets-io` is required when you import XLSX files into a workbook.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css';
> ```

#### Step 3: Configure the SpreadJS workbook with the Velt Comments extension

Create the workbook, import your spreadsheet, then attach `SpreadJSVeltComments` after the import completes. The same workbook instance is used by `addComment` and `renderComments`.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { useEffect, useRef, useState } from 'react';
> import { useCommentAnnotations } from '@veltdev/react';
> import {
>   SpreadJSVeltComments,
>   renderComments,
>   type AttachedExtension,
>   type SpreadInstance,
> } from '@veltdev/spreadjs-velt-comments';
>
> const EDITOR_ID = 'my-workbook';
>
> function SpreadsheetEditor() {
>   const hostRef = useRef<HTMLDivElement | null>(null);
>   const workbookRef = useRef<SpreadInstance | null>(null);
>   const extensionRef = useRef<AttachedExtension | null>(null);
>   const [instance, setInstance] = useState<SpreadInstance | null>(null);
>   const annotations = useCommentAnnotations();
>
>   useEffect(() => {
>     if (!hostRef.current || workbookRef.current) return;
>
>     let cancelled = false;
>     const host = hostRef.current;
>
>     import('@mescius/spread-sheets').then(async (spreadModule) => {
>       const GC = 'default' in spreadModule ? spreadModule.default : spreadModule;
>       await import('@mescius/spread-sheets-io');
>       if (cancelled || workbookRef.current) return;
>
>       const workbook = new GC.Spread.Sheets.Workbook(host);
>       workbookRef.current = workbook;
>
>       const response = await fetch('/your-workbook.xlsx');
>       const file = new File([await response.blob()], 'your-workbook.xlsx');
>
>       workbook.import(
>         file,
>         () => {
>           if (cancelled) return;
>
>           extensionRef.current = SpreadJSVeltComments
>             .configure({ editorId: EDITOR_ID })
>             .attach(workbook);
>           setInstance(workbook);
>         },
>         (error: unknown) => console.error('XLSX import failed', error),
>         { fileType: GC.Spread.Sheets.FileType.excel },
>       );
>     });
>
>     return () => {
>       cancelled = true;
>       extensionRef.current?.detach();
>       workbookRef.current?.destroy();
>       workbookRef.current = null;
>       setInstance(null);
>     };
>   }, []);
>
>   useEffect(() => {
>     if (!instance) return;
>
>     renderComments({
>       instance,
>       commentAnnotations: annotations ?? [],
>     });
>   }, [instance, annotations]);
>
>   return <div ref={hostRef} style={{ width: '100%', height: '100vh' }} />;
> }
> ```

#### Step 4: Add a comment button to your SpreadJS workbook

SpreadJS renders the grid to a canvas, so there is no DOM text selection for a default text bubble menu. Add a toolbar button or contextual selection bubble that uses the workbook's selected cell/range state, then call `addComment({ instance })`.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { addComment } from '@veltdev/spreadjs-velt-comments';
>
> const handleAddComment = async () => {
>   if (!instance) return;
>
>   const result = await addComment({ instance });
>   if (!result) {
>     console.warn('Select a cell or range before adding a comment.');
>   }
> };
>
> <button onClick={handleAddComment}>Add Comment</button>
> ```

#### Step 5: Call `addComment` to add a comment

* Call this method to add a comment to the currently selected cell or range.
* Params: [`AddCommentArgs`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-addcommentargs). It has the following properties:
  * `instance`: SpreadJS workbook instance created with `new GC.Spread.Sheets.Workbook(host)`.
* Returns: [`Promise<AddCommentResult | null>`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-addcommentresult). It returns `null` if no cell/range is selected or Velt is not loaded.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { addComment } from '@veltdev/spreadjs-velt-comments';
>
> const result = await addComment({ instance });
> ```

To scope comments to a specific workbook on pages with multiple SpreadJS instances, pass an editor id when attaching the extension:

```tsx theme={null}
SpreadJSVeltComments.configure({ editorId: 'EDITOR_ID' }).attach(workbook);
```

#### Step 6: Render comments in SpreadJS workbook

* Get comment data from the Velt SDK and render it in the SpreadJS workbook.
* Params: [`RenderCommentsArgs`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-rendercommentsargs). It has the following properties:
  * `instance`: SpreadJS workbook instance.
  * `commentAnnotations`: Array of Comment Annotation objects.

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { useEffect } from 'react';
> import { useCommentAnnotations } from '@veltdev/react';
> import { renderComments } from '@veltdev/spreadjs-velt-comments';
>
> const commentAnnotations = useCommentAnnotations();
>
> useEffect(() => {
>   if (!instance) return;
>
>   renderComments({
>     instance,
>     commentAnnotations: commentAnnotations ?? [],
>   });
> }, [instance, commentAnnotations]);
> ```

Highlights are view-only. The library re-derives each highlight from its [`TextEditorConfig`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-texteditorconfig) anchor and SpreadJS repositions the overlays across scroll, zoom, row/column resize, and sheet changes. Re-run `renderComments` when Velt's annotation list changes or when you import a new workbook.

#### Step 7: Clean up the Velt SpreadJS extension

`SpreadJSVeltComments.configure(...).attach(instance)` returns an [`AttachedExtension`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-attachedextension). Call `detach()` in your effect cleanup to remove listeners, clear per-instance state, and remove overlay elements before destroying the workbook.

```tsx theme={null}
return () => {
  extensionRef.current?.detach();
  extensionRef.current = null;
  workbookRef.current?.destroy();
};
```

#### Step 8: Style the commented text

* Each comment is rendered through a `.velt-spreadjs-overlay` layer with a `.velt-spreadjs-highlight` range fill and a `velt-comment-text` marker.
* Override the default inline highlight styles with `!important`.

```css theme={null}
.velt-spreadjs-highlight {
  background-color: rgba(255, 212, 0, 0.36) !important;
  border: 1.5px solid rgba(255, 170, 0, 0.95) !important;
}

velt-comment-text:hover .velt-spreadjs-highlight,
velt-comment-text[comment-selected="true"] .velt-spreadjs-highlight,
velt-comment-text.velt-comment-selected .velt-spreadjs-highlight {
  background-color: rgba(255, 212, 0, 0.62) !important;
}
```

## Complete Example

[https://sample-apps-spreadjs-comments-demo.vercel.app/](https://sample-apps-spreadjs-comments-demo.vercel.app/)

## APIs

#### [SpreadJSVeltComments](https://velt.dev/docs/api-reference/sdk/api/api-methods.md#spreadjs-spreadjsveltcomments)

Creates the Velt Comments extension for a SpreadJS workbook. Use `SpreadJSVeltComments.configure(...).attach(instance)` to attach it to a workbook instance.

* Config: [`SpreadJSVeltCommentsConfig`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-spreadjsveltcommentsconfig)
* Returns: `SpreadJSVeltComments`

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { SpreadJSVeltComments } from '@veltdev/spreadjs-velt-comments';
>
> const attached = SpreadJSVeltComments
>   .configure({ editorId: 'my-workbook' })
>   .attach(instance);
>
> attached.detach();
> ```

#### [addComment()](https://velt.dev/docs/api-reference/sdk/api/api-methods.md#spreadjs-addcomment)

Creates a comment annotation for the currently selected SpreadJS cell or range.

* Signature: `async (args: AddCommentArgs) => Promise<AddCommentResult | null>`
* Params: `args:` [`AddCommentArgs`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-addcommentargs)
* Returns: `Promise<AddCommentResult | null>`; see [`AddCommentResult`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-addcommentresult).

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { addComment } from '@veltdev/spreadjs-velt-comments';
>
> const result = await addComment({ instance });
> ```

#### [renderComments()](https://velt.dev/docs/api-reference/sdk/api/api-methods.md#spreadjs-rendercomments)

Renders and updates Velt comment highlights in the SpreadJS workbook.

* Signature: `(args:` [`RenderCommentsArgs`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-rendercommentsargs)`) => void`
* Params: `args:` [`RenderCommentsArgs`](https://velt.dev/docs/api-reference/sdk/models/data-models#spreadjs-rendercommentsargs)
* Returns: `void`

> [tab] React / Next.js
>
> ```tsx theme={null}
> import { renderComments } from '@veltdev/spreadjs-velt-comments';
>
> renderComments({
>   instance,
>   commentAnnotations: annotations ?? [],
> });
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.