Bundleware, Toolbar Script Reference

Last site update 30th October 2026

Write a toolbar

// ==BundlewareToolbar==
// @id my-counter
// @name My Counter
// @version 1.0.0
// @description A small local counter.
// @match <all_urls>
// @api 2
// ==/BundlewareToolbar==

const { Toolbar, Action, Icon, store, useStore } = Bundleware;

const counter = store({ count: 0 });

function MyCounter() {
  const [state, setState] = useStore(counter);
  return (
    <Toolbar icon={Icon.Palette} theme={{ brandColor: '#315b87' }}>
      <Toolbar.Button title={`Count: ${state.count}`} icon={Icon.Sound} onAction={() => setState({ count: state.count + 1 })} />
      <Toolbar.Button title="Details" action={<Action.OpenWindow title="Counter" target={<Details />} />} />
    </Toolbar>
  );
}

function Details(props) {
  const [state] = useStore(counter);
  return <><p>Clicked {state.count} times.</p><button onClick={props.close}>Done</button></>;
}

Bundleware.defineToolbar(<MyCounter />);

examples/toolbar-script/ has more. The bundled toolbars in src/toolbars/ are written the same way, in TypeScript, and checked with strict by src/toolbars/tsconfig.json. For checking and completion in any editor, put public/bundleware.d.ts beside your script with a tsconfig.json like that one: "jsx": "react", "jsxFactory": "Bundleware.h", "jsxFragmentFactory": "Bundleware.Fragment", "moduleDetection": "force" and "types": []. The API's types are in the BundlewareAPI namespace: function Details(props: BundlewareAPI.WindowProps & { id: string }), const theme: BundlewareAPI.ToolbarTheme = {…}, useRef<HTMLInputElement>(null). A window body's close is given by the host, so openWindow(<Details id="a" />, …) need not pass it. For a .jsx script, the example's jsconfig.json and // @ts-check with JSDoc types do the same.