Reference
CSS and UI-provider requirements
Design tokens, stylesheet order, Tailwind sources and the UI kit each surface needs.
- Design tokens:
@skaile/forge-editor/styles/tokens.cssdeclares the shared--sk-*variables (--sk-bg,--sk-fg,--sk-muted,--sk-border,--sk-primary,--sk-primary-fg,--sk-success,--sk-warning,--sk-danger,--sk-radius,--sk-font) with light defaults under:where(:root)and dark values under:where(.dark). Every feature stylesheet reads them; a UI kit maps them onto its own variables (Nuxt UI:vue/kit/nuxt-ui.css, React/shadcn:react/styles/ui-vars.css), a host may override them once. - Basket colours:
@skaile/forge-editor/styles/composites.cssdeclares the colours of the default colour Baskets (compositeFeature({ baskets })) as--sk-basket-red,--sk-basket-orange,--sk-basket-yellow,--sk-basket-greenand--sk-basket-blue, light values under:where(:root)and dark values under:where(.dark)like the design tokens, so a host overrides them once. A custom Basket brings its owncolor. The Typed block's node view sets--sk-basket-coloron a Typed block in a Basket; the stripe reads it. - Block type tone: a Block type with
chrome.tone(BlockType, any CSS colour orvar(...)) sets its Typed blocks apart. The Typed block's node view setsdata-block-type-toneand--sk-block-type-toneon the wrapper of such a Typed block;composites.csstints its surface with the tone and paints the left border in it (a Basket stripe still wins on the border), and the Document tree rows of the Block type tint the Block type icon. How strong the tint is comes from--sk-block-type-tone-mix(8%under:where(:root),14%under:where(.dark), like the Basket colours). A Block type without a tone is untouched. - Vue UI kit: the Vue binding is built on Nuxt UI. The chrome renders through the kit handed to
createEditor({ kit });kitis optional and defaults tonuxtUiKit()(@skaile/forge-editor/vue/kit/nuxt-ui, needs@nuxt/ui, stylesheet@skaile/forge-editor/vue/kit/nuxt-ui.css).@skaile/forge-editor/vue/kitholds theVueUiKitcontract anduseUiKit(); pass your ownVueUiKitonly to render the chrome with another library. Only thenuxt-uikit entry imports@nuxt/ui. The Nuxt module has nokitoption: it always addsvue/kit/nuxt-ui.css, patches Nuxt UI'sui.cssso Tailwind scans the package (@nuxt/uimust be registered before the module) and installs the Nuxt UI context plugin. - Import the core CSS after Tailwind and Nuxt UI, and let Tailwind see the library's classes. Scan the whole
distof the package (Vue files indist/vueanddist/features/*/components, React files indist/reactanddist/features/*/react), never a single subdirectory; in this repository the examples scanpackages/editor/src:@import "tailwindcss"; @import "@nuxt/ui"; @import "@skaile/forge-editor/styles/core.css"; @source "../node_modules/@skaile/forge-editor/dist"; /* relative path from this CSS file to the installed package's dist */
The Nuxt module needs none of this: it addscore.cssand every feature sheet tocss(themes.csslast) and appends the package to Tailwind's@sourcelist. In plain Vue also import the sheet of each feature you use, e.g.@skaile/forge-editor/styles/media.css, aftercore.css. The AI sidebar (@skaile/forge-editor/ai/vue/chat) renders on the optional peer@skaile/forge-chat, whose resources the host owns, in Nuxt as well: import@skaile/forge-chat/styles/chat.css, add@sourcefor@skaile/forge-chat/dist(e.g.@source "../../../node_modules/@skaile/forge-chat/dist";) and, in Nuxt,'@skaile/forge-chat/nuxt'after'@nuxt/ui'inmodules.styles/ai.cssno longer imports the chat stylesheet. - Plain Vue: Vite plugins
vue()andui({ router: false })from@nuxt/ui/vite,app.use(ui)withimport ui from '@nuxt/ui/vue-plugin', and the editor contextapp.use(createEditor())(createEditorfrom@skaile/forge-editor/vue). Wrap the page in<UApp>(overlays, toasts, tooltips). - React: Vite with
@vitejs/plugin-reactand@tailwindcss/vite. The CSS needs Tailwind,tw-animate-css,@skaile/forge-editor/react/styles/ui-vars.css,core.css(plus the sheet of each feature you use, e.g.mentions.css), the shadcn theme block (:root/.darktokens and@theme inline;bunx shadcn@latest initgenerates it) and@sourcefor the library's wholedist(@source "../node_modules/@skaile/forge-editor/dist";): the Features' React components live indist/features/*/react, not indist/react. For the advanced editor import@skaile/forge-editor/react/styles/advanced.cssinstead of those three library sheets: it bundlesui-vars.css,core.css, every feature sheet andthemes.css(last). Preload the icons withaddCollection(lucide)from@iconify/react, wrap the tree in<EditorContextProvider context={createEditorContext({ notify: reactNotifier })}>and mount<Toaster />(sonner, from@skaile/forge-editor/react) once so notices show up; see the usage guide, Advanced editor in React,examples/react-simpleandexamples/react-advanced. - Icons: Nuxt UI resolves
i-lucide-*names at build time. A workspace library lies outside the Vite root that Nuxt UI scans, so list its icons for the client bundle (see howexamples/vue-simple/vite.config.tscollects them) to avoid Iconify API requests at runtime. - The editor context is mandatory: Vue
EditorSurface,SimpleEditorandEditorToolbarthrow a descriptive error withoutcreateEditor(), the React components without<EditorContextProvider>. Both wrap the framework-freecreateEditorContext()from@skaile/forge-editor/core; the host owns the React context and may callcontext.dispose()itself.