Plugins
A pantoken plugin extends the token or CSS output without forking a package. You build one with definePlugin from @pantoken/plugin-kit, then pass it to buildTokens or toCss.
Author a plugin
Give definePlugin the hooks you implement. It returns a normal plugin, branded with the capabilities inferred from those hooks. A plugin can extend the IR (tokens, icons), the CSS output (css), or both.
import { definePlugin } from "@pantoken/plugin-kit";
export const brand = () =>
definePlugin({
name: "@acme/brand",
tokens: (ctx) => [...ctx.tokens /* add records */],
css: () => ({ append: ":root { /* … */ }" }),
});Capability-aware registration
buildTokens and toCss run checkPlugins over the plugins you pass. It warns — it never throws — when a plugin has no matching hook for the stage it's registered in, so a token-only plugin passed to toCss is skipped with a note rather than silently doing nothing.
Compose plugins
Build on top of another plugin with extendPlugin, or combine peers with mergePlugin:
import { extendPlugin, mergePlugin } from "@pantoken/plugin-kit";
const themed = extendPlugin(brand(), { css: () => ({ append: "/* extra */" }) });
const both = mergePlugin(brand(), icons());Same-stage hooks compose: tokens runs the base then the addition, css merges the two contributions, and icons runs both.
Validate your plugin's output
Run the shared drift checks from @pantoken/utils over your plugin's own output in its test, so a typo or a renamed token fails fast and locally:
import { danglingReferences, unknownReferences } from "@pantoken/utils";
import { tokens } from "@pantoken/tokens";
// A self-contained contribution defines what it references, so nothing should dangle.
expect(danglingReferences(myPlugin().css!({ tokens, css: "" }).append ?? "")).toEqual([]);
// A contribution that only references tokens defined elsewhere: every target must be a real token.
expect(unknownReferences(myBridgeCss, tokens)).toEqual([]);The bundled plugins
@pantoken/plugin-simple-icons— brand icons from simple-icons, registered as icon tokens.@pantoken/plugin-logos— Instructure product logos as SVGs, data URIs, and--instui-logo-*image tokens.@pantoken/plugin-prune-custom-props— a PostCSS plugin (not a pantoken plugin) that drops unused custom properties from a stylesheet.
A few things that used to be plugins now ship in @pantoken/components, since so many components need them out of the box: elevation shadows (--instui-elevation-*, in components.css), the focus-outline ring (in base.css — every focusable gets it when pantoken owns the page), and the Instructure brand fonts (Atkinson Hyperlegible Next: base.css applies --instui-font-family-base; the opt-in @pantoken/components/fonts.css loads the @font-face woff2s).
See the API reference for each plugin's exports.