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

# List item

export const SourceCodeLink = ({extension, path}) => {
  const githubPath = path || `packages/super-editor/src/editors/v1/extensions/${extension.toLowerCase()}`;
  const githubUrl = `https://github.com/superdoc-dev/superdoc/tree/main/${githubPath}`;
  return <div>
      <p>
        <a href={githubUrl} target="_blank" rel="noopener noreferrer">
          View on GitHub →
        </a>
      </p>
    </div>;
};

export const SuperDocEditor = ({html = '<p>Start editing...</p>', height = '400px', maxHeight = '400px', onReady = null, showExport = true, customButtons = null}) => {
  const [ready, setReady] = useState(false);
  const editorRef = useRef(null);
  const containerIdRef = useRef(`editor-${Math.random().toString(36).substr(2, 9)}`);
  const DEV_DIST_URL = 'http://localhost:9094/dist';
  const UNPKG_DIST_URL = 'https://unpkg.com/superdoc@latest/dist';
  const getBaseUrl = async () => {
    const isDev = typeof window !== 'undefined' && window.location.hostname === 'localhost';
    if (isDev) {
      try {
        const res = await fetch(`${DEV_DIST_URL}/superdoc.min.js`, {
          method: 'HEAD'
        });
        if (res.ok) {
          console.info('[SuperDoc Docs] Using local build from', DEV_DIST_URL);
          return DEV_DIST_URL;
        }
        console.warn('[SuperDoc Docs] Local dev server returned', res.status, '- falling back to unpkg');
      } catch (err) {
        console.warn('[SuperDoc Docs] Local dev server not reachable: falling back to unpkg.', 'Run `pnpm dev:docs` from the repo root to use your local build.', err.message);
      }
    }
    return UNPKG_DIST_URL;
  };
  const ensureStyle = baseUrl => {
    const styleHref = `${baseUrl}/style.css`;
    if (document.querySelector(`link[href="${styleHref}"]`)) return;
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = styleHref;
    document.head.appendChild(link);
  };
  const loadSuperDoc = baseUrl => {
    if (window.SuperDoc) return Promise.resolve();
    const scriptSrc = `${baseUrl}/superdoc.min.js`;
    const existingScript = document.querySelector(`script[src="${scriptSrc}"]`);
    if (existingScript) {
      if (window.SuperDoc) return Promise.resolve();
      return new Promise((resolve, reject) => {
        existingScript.addEventListener('load', resolve, {
          once: true
        });
        existingScript.addEventListener('error', reject, {
          once: true
        });
      });
    }
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = scriptSrc;
      script.onload = resolve;
      script.onerror = reject;
      document.body.appendChild(script);
    });
  };
  const initEditor = () => {
    setTimeout(() => {
      if (!window.SuperDoc) return;
      if (!document.getElementById(containerIdRef.current)) return;
      if (editorRef.current) return;
      editorRef.current = new window.SuperDoc({
        selector: `#${containerIdRef.current}`,
        html,
        rulers: true,
        contained: true,
        onReady: () => {
          setReady(true);
          if (onReady) onReady(editorRef.current);
        }
      });
    }, 100);
  };
  useEffect(() => {
    let cancelled = false;
    const boot = async () => {
      try {
        const baseUrl = await getBaseUrl();
        ensureStyle(baseUrl);
        await loadSuperDoc(baseUrl);
        if (!cancelled) initEditor();
      } catch (error) {
        console.error('Failed to boot SuperDoc:', error);
      }
    };
    boot();
    return () => {
      cancelled = true;
      editorRef.current?.destroy?.();
      editorRef.current = null;
    };
  }, []);
  const exportDocx = () => {
    if (editorRef.current?.export) {
      editorRef.current.export();
    }
  };
  return <div className="border rounded-lg bg-white overflow-hidden">
      {ready && (showExport || customButtons) && <div className="px-3 py-2 bg-gray-50 border-b">
          {customButtons && <div className="space-y-1 mb-2">
              {customButtons.map((row, rowIndex) => <div key={rowIndex} className="flex gap-1">
                  {row.map((btn, i) => <button key={i} onClick={() => btn.onClick(editorRef.current)} className={btn.className || 'flex-1 px-2 py-1 bg-gray-100 text-gray-700 text-xs rounded hover:bg-gray-200'}>
                      {btn.label}
                    </button>)}
                </div>)}
            </div>}
          {showExport && <div className="text-right">
              <button onClick={exportDocx} className="px-3 py-1 bg-blue-500 text-white text-xs rounded hover:bg-blue-600">
                Export DOCX
              </button>
            </div>}
        </div>}
      <div id={containerIdRef.current} style={{
    height,
    maxHeight,
    paddingLeft: '5px'
  }} />
      <style jsx>{`
        #${containerIdRef.current} .superdoc__layers {
          max-width: 660px !important;
        }
        #${containerIdRef.current} .super-editor {
          max-width: 100% !important;
          width: 100% !important;
          color: #000;
        }
        #${containerIdRef.current} .editor-element {
          width: 100% !important;
          min-width: unset !important;
          transform: none !important;
        }
        #${containerIdRef.current} .editor-element {
          h1,
          h2,
          h3,
          h4,
          h5,
          strong {
            color: #000;
          }
        }
      `}</style>
    </div>;
};

The foundation node for both bullet and numbered lists with Word-compatible formatting.

Handles numbering, indentation, styling, and keyboard navigation for professional list creation.

<SuperDocEditor
  html={`
<ul>
  <li>Basic bullet list item with standard formatting</li>
  <li>Second item - press Tab to indent, Shift-Tab to outdent</li>
  <li>Press Enter to create a new item, Shift-Enter for line break within item</li>
</ul>
<ol>
  <li>Numbered lists automatically track numbering</li>
  <li>Supports multiple numbering formats from Word:
    <ol>
      <li>Decimal numbers (1, 2, 3)</li>
      <li>Letters (a, b, c) or (A, B, C)</li>
      <li>Roman numerals (i, ii, iii) or (I, II, III)</li>
    </ol>
  </li>
  <li>Maintains Word numbering definitions and styles</li>
</ol>
`}
  height="400px"
  customButtons={[
[
  {
    label: 'Bullet List',
    onClick: (superdoc) => {
      const editor = superdoc?.activeEditor || superdoc?.editor
      if (!editor?.commands) return
      editor.commands.toggleBulletList()
    }
  },
  {
    label: 'Numbered List',
    onClick: (superdoc) => {
      const editor = superdoc?.activeEditor || superdoc?.editor
      if (!editor?.commands) return
      editor.commands.toggleOrderedList()
    }
  },
  {
    label: 'Indent →',
    onClick: (superdoc) => {
      const editor = superdoc?.activeEditor || superdoc?.editor
      if (!editor?.commands) return
      editor.commands.increaseListIndent()
    }
  },
  {
    label: '← Outdent',
    onClick: (superdoc) => {
      const editor = superdoc?.activeEditor || superdoc?.editor
      if (!editor?.commands) return
      editor.commands.decreaseListIndent()
    }
  }
]
]}
/>

## Key features

### Custom node view

The list item uses a custom node view that provides:

* **Visual numbering/bullets** - Rendered separately from content
* **Smart indentation** - Calculates proper spacing based on Word styles
* **Font inheritance** - Respects document and paragraph styles
* **Marker alignment** - Handles left, right, and centered numbering

### Word compatibility attributes

The list item maintains numerous Word-specific attributes:

* `numId` - Links to Word numbering definition
* `level` - Tracks nesting depth (0-8)
* `lvlText` - Format string for numbering
* `listNumberingType` - decimal, upperRoman, lowerAlpha, etc.
* `indent` - Precise indentation values
* `spacing` - Line and paragraph spacing

## OOXML Structure

```xml theme={null}
<w:p>
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0"/>
      <w:numId w:val="1"/>
    </w:numPr>
  </w:pPr>
  <w:r>
    <w:t>List item content</w:t>
  </w:r>
</w:p>
```

## Keyboard shortcuts

| Action     | Shortcut      | Description                               |
| ---------- | ------------- | ----------------------------------------- |
| New Item   | `Enter`       | Creates a new list item at the same level |
| Line Break | `Shift+Enter` | Adds a line break within the current item |
| Indent     | `Tab`         | Increases nesting level                   |
| Outdent    | `Shift+Tab`   | Decreases nesting level                   |
| Exit List  | `Enter` twice | Creates a paragraph after the list        |

## Numbering formats

### Standard formats

* **Decimal** - 1, 2, 3, 4...
* **Lower Alpha** - a, b, c, d...
* **Upper Alpha** - A, B, C, D...
* **Lower Roman** - i, ii, iii, iv...
* **Upper Roman** - I, II, III, IV...

### Custom formats

Word supports complex numbering like:

* **Legal** - 1.1, 1.2, 1.2.1, 1.2.2...
* **Outline** - I.A.1.a.i...
* **Custom** - Chapter 1, Section A, Article i...

## Use case

* **Document Structure** - Organize content hierarchically
* **Instructions** - Step-by-step procedures
* **Outlines** - Multi-level document planning
* **Legal Documents** - Complex numbered sections
* **Word Import/Export** - Perfect numbering preservation

<Info>
  List item behavior is handled by the [Paragraph extension](/extensions/paragraph). Lists in SuperDoc are paragraphs with numbering properties, matching how Word stores lists internally.
</Info>

## Keyboard shortcuts

| Command      | Shortcut      | Description                              |
| ------------ | ------------- | ---------------------------------------- |
| (split item) | `Enter`       | Split list item at cursor                |
| (line break) | `Shift-Enter` | Add a line break within the current item |
| (indent)     | `Tab`         | Increase nesting level                   |
| (outdent)    | `Shift-Tab`   | Decrease nesting level                   |

## Numbering formats

Supported numbering formats from Word:

* **Decimal** — 1, 2, 3, 4...
* **Lower alpha** — a, b, c, d...
* **Upper alpha** — A, B, C, D...
* **Lower roman** — i, ii, iii, iv...
* **Upper roman** — I, II, III, IV...

## Source code

<SourceCodeLink path="packages/super-editor/src/editors/v1/extensions/paragraph/paragraph.js" />
