Web Component Recipe

A web component is registered as view.component and normally renders in a shadow root. Choose the smallest valid setup.

These are integration recipes for an existing Vue/Vite project. They show the Wippy-specific element, metadata, and build configuration rather than a standalone project scaffold.

Variant A: content-only

A chart, diagram, renderer, or visualization may omit PrimeVue and Tailwind when it renders no control and authors no shared Tailwind utility.

It still must:

  • Publish a valid custom-element tag.
  • Preserve accessibility for rendered content.
  • Use supported Wippy configuration and CSS delivery.
  • Avoid project-private facade classes.
  • Build through the Wippy module repository's canonical Make target.

If a button, input, form, menu, or other PrimeVue-like control is later added, this exemption ends.

Variant B: control-bearing

A component with controls must install PrimeVue through the Wippy PrimeVue plugin and receive the host's theme and PrimeVue CSS. The web-component package loads all host CSS keys by default; the explicit list below narrows that default to the assets this example uses plus the shared iframe/scrollbar CSS:

import { defineComponent, h } from 'vue'
import Button from 'primevue/button'
import { PrimeVuePlugin } from '@wippy-fe/theme/primevue-plugin'
import {
  WippyVueElement,
  define,
  type WippyElementConfig,
} from '@wippy-fe/webcomponent-vue'
import pkg from '../package.json'

const Root = defineComponent({
  name: 'ExampleControlsRoot',
  setup() {
    return () => h(Button, { label: 'Save' })
  },
})

class ExampleControlsElement extends WippyVueElement {
  static get wippyConfig(): WippyElementConfig {
    return {
      propsSchema: pkg.wippy.props,
      hostCssKeys: ['themeConfigUrl', 'primeVueCssUrl', 'iframeCssUrl'],
    }
  }

  static get vueConfig() {
    return {
      rootComponent: Root,
      plugins: [PrimeVuePlugin],
    }
  }
}

export async function webComponent() {
  return ExampleControlsElement
}

define(import.meta.url, ExampleControlsElement)

Package metadata contract

The package metadata must identify the same custom element:

{
  "name": "@example/controls",
  "version": "0.1.0",
  "type": "module",
  "specification": "wippy-component-1.0",
  "browser": "dist/index.js",
  "wippy": {
    "type": "component",
    "tagName": "example-controls",
    "props": {
      "type": "object",
      "properties": {},
      "additionalProperties": false
    }
  }
}

Valid package wippy.type values are "component" and "widget". Do not use the registry kind view.component as a package wippy.type value.

The component build uses the strict Wippy component plugin and the complete pinned target-host import-map snapshot:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { wippyComponentPlugin } from '@wippy-fe/vite-plugin'
import hostImportMap from './wippy-import-map.json'

export default defineConfig({
  plugins: [vue(), wippyComponentPlugin({ required: true })],
  build: {
    lib: {
      entry: 'src/element.ts',
      formats: ['es'],
      fileName: 'index',
    },
    rollupOptions: {
      external: Object.keys(hostImportMap.imports),
      preserveEntrySignatures: 'strict',
    },
  },
})

Keep preserveEntrySignatures: 'strict'. Other Rollup values do not satisfy the Wippy component build contract documented here.

Use the shared Wippy Tailwind preset when this component authors Tailwind utilities. PrimeVue itself does not require a module to invent Tailwind utilities.

Shadow-root rules

  • Public CSS variables may inherit into the shadow root.
  • Selector rules take effect only if the host delivers them into the root.
  • Shared PrimeVue theme CSS is a supported dependency.
  • Arbitrary facade classes are not portable APIs.
  • Overlay placement must be verified in the real runtime; do not force a generic placement recipe.

Metadata and build

Document props and events in package metadata. A registry entry may repeat them as deployment-specific meta.props and meta.events overrides; when present, those overrides take precedence over the bundled metadata. Invoke the module repository's Make target; its recipe uses:

npm run build -- --outDir <target> --emptyOutDir

Do not invoke that underlying command directly. On Windows, invoke make.bat; it delegates to make.ps1.

See Theme Authoring, Tailwind Contract, and Build and Dependency Contract.