Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ const superdoc = new SuperDoc({
});
```

Optional layered CSS mode:

```css
@layer reset, superdoc, app;
@import 'superdoc/style.layered.css';
@import 'your-app.css' layer(app);
```

Or use the CDN:

```html
Expand Down
16 changes: 16 additions & 0 deletions apps/docs/editor/theming/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ document.documentElement.classList.add(theme);

Five properties theme the entire UI.

## Optional layered stylesheet

Default usage remains:

```javascript
import 'superdoc/style.css';
```

If your application uses CSS cascade layers and you want explicit layer ordering, use:

```css
@layer reset, superdoc, app;
@import 'superdoc/style.layered.css';
@import 'your-app.css' layer(app);
```

## `createTheme()`

Pass a config object, get back a CSS class name. Apply it to `<html>`.
Expand Down
16 changes: 16 additions & 0 deletions apps/docs/getting-started/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ new SuperDoc({ selector: '#editor', document: 'contract.docx' });

Toolbar buttons, comments sidebar, dropdowns, context menu, search bar, dialog surfaces. Any chrome SuperDoc renders. The document content itself (paragraphs, headings, tables) renders with its own styles from the DOCX.

## Optional layered stylesheet

By default, you can keep using:

```javascript
import 'superdoc/style.css';
```

If your app uses cascade layers and you want SuperDoc styles in a named layer, use the optional layered entrypoint:

```css
@layer reset, superdoc, app;
@import 'superdoc/style.layered.css';
@import 'your-app.css' layer(app);
```

## When to drop to CSS variables

`createTheme()` covers the common case. For component-level overrides, use the `vars` option or set raw `--sd-*` variables in your stylesheet:
Expand Down
13 changes: 13 additions & 0 deletions packages/superdoc/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ const theme = createTheme({
document.documentElement.classList.add(theme);
```

CSS entrypoints:

- `superdoc/style.css` — standard stylesheet.
- `superdoc/style.layered.css` — optional layered stylesheet wrapped in `@layer superdoc`.

Recommended layered setup:

```css
@layer reset, superdoc, app;
@import 'superdoc/style.layered.css';
@import 'your-app.css' layer(app);
```

Docs: https://docs.superdoc.dev/getting-started/theming

## Document Engine — programmatic access
Expand Down
3 changes: 2 additions & 1 deletion packages/superdoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
"types": "./dist/superdoc/src/public/legacy/file-zipper.d.ts",
"import": "./dist/super-editor/file-zipper.es.js"
},
"./style.css": "./dist/style.css"
"./style.css": "./dist/style.css",
"./style.layered.css": "./dist/style.layered.css"
},
"types": "./dist/superdoc/src/public/index.d.ts",
"typesVersions": {
Expand Down
1 change: 1 addition & 0 deletions packages/superdoc/scripts/type-surface.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ const publicContract = {
],
asset: [
{ subpath: './style.css', tier: 'asset', note: 'CSS bundle; no types' },
{ subpath: './style.layered.css', tier: 'asset', note: 'Layered CSS bundle; no types' },
],
deprecated: [],
};
Expand Down
32 changes: 32 additions & 0 deletions packages/superdoc/vite-plugin-layered-css.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import fs from 'node:fs';
import path from 'node:path';

export default function layeredCssPlugin() {
return {
name: 'superdoc-layered-css',
writeBundle(outputOptions, bundle) {
const cssAssets = Object.entries(bundle).filter(([, chunk]) => {
return chunk.type === 'asset' && typeof chunk.fileName === 'string' && chunk.fileName.endsWith('.css');
});

if (cssAssets.length === 0) {
return;
}

const targetAsset =
cssAssets.find(([fileName]) => fileName === 'style.css') ??
cssAssets[0];

const [, chunk] = targetAsset;
const source = typeof chunk.source === 'string'
? chunk.source
: Buffer.from(chunk.source).toString('utf8');

const layeredCss = `@layer superdoc{${source}}\n`;
const outDir = outputOptions.dir ?? path.dirname(outputOptions.file ?? '');
const layeredFilePath = path.join(outDir, 'style.layered.css');

fs.writeFileSync(layeredFilePath, layeredCss);
},
};
}
3 changes: 2 additions & 1 deletion packages/superdoc/vite.config.cdn.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
import { version } from './package.json';
import { getAliases } from './vite.config.js';
import layeredCssPlugin from './vite-plugin-layered-css.mjs';

// Standalone browser bundle for CDN / <script> tag consumption.
// Exposes `window.SuperDoc`. Inlines all runtime deps (Vue, ProseMirror,
// Yjs, Hocuspocus) so a single <script> tag is enough — these peers are
// ESM-only and can't be loaded as globals. Only pdfjs-dist stays external
// because of its size; PDF viewing requires the ESM + import-map path.
export default defineConfig(({ command }) => {
const plugins = [vue()];
const plugins = [vue(), layeredCssPlugin()];
const isDev = command === 'serve';

return {
Expand Down
2 changes: 2 additions & 0 deletions packages/superdoc/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { fileURLToPath, URL } from 'node:url';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import { visualizer } from 'rollup-plugin-visualizer';
import vue from '@vitejs/plugin-vue'
import layeredCssPlugin from './vite-plugin-layered-css.mjs';

import { version } from './package.json';
import sourceResolve from '../../vite.sourceResolve';
Expand Down Expand Up @@ -118,6 +119,7 @@ export default defineConfig(({ mode, command }) => {
const skipDts = process.env.SUPERDOC_SKIP_DTS === '1';
const plugins = [
vue(),
layeredCssPlugin(),
!skipDts && dts({
// Foundational sources (superdoc, super-editor, document-api) are
// always included; relocation patterns come from the canonical
Expand Down
Loading