> ## Documentation Index
> Fetch the complete documentation index at: https://webview.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# WebviewJS on macOS: WebKit, Titlebar and Native Tab APIs

> Platform-specific notes for WebviewJS on macOS, including WebKit version, titlebar customization, native tabs, shadow control, and threading requirements.

WebviewJS on macOS uses the built-in **WebKit** engine (`WKWebView`) — the same engine that powers Safari. No additional runtime installation is needed; WebKit is part of the operating system. **macOS 10.15 Catalina or later** is required.

## Supported architectures

| Target triple          | Architecture          | CI |
| ---------------------- | --------------------- | -- |
| `x86_64-apple-darwin`  | x64 (Intel)           | ✅  |
| `aarch64-apple-darwin` | arm64 (Apple Silicon) | ✅  |

Universal binaries (fat binaries targeting both slices) can be produced during the build step. See the [Building Executables guide](/guides/building-executables) for details.

## Threading requirement

<Warning>
  macOS enforces that **all GUI operations run on the main thread**. Do **not**
  create `Application` or `BrowserWindow` from a `worker_threads` Worker or
  any async context that migrates the call off the main thread. WebviewJS
  handles main-thread dispatch internally, but the initial construction calls
  must originate from the main thread.
</Warning>

## macOS-specific creation options

Pass these fields in `BrowserWindowOptions` when calling `app.createBrowserWindow()`. They are silently ignored on other platforms.

| Option                           | Type      | Description                                                                                        |
| -------------------------------- | --------- | -------------------------------------------------------------------------------------------------- |
| `macosMovableByWindowBackground` | `boolean` | Allow the user to drag the window by clicking anywhere on the background (not just the title bar). |
| `macosTitlebarTransparent`       | `boolean` | Render the title bar with a transparent background, letting window content show through.           |
| `macosTitleHidden`               | `boolean` | Hide the window title text while keeping the title bar visible.                                    |
| `macosTitlebarHidden`            | `boolean` | Remove the title bar entirely, producing a fully content-filled window.                            |
| `macosTitlebarButtonsHidden`     | `boolean` | Hide the traffic-light buttons (close, minimize, zoom) without removing the title bar.             |
| `macosFullsizeContentView`       | `boolean` | Extend the content view behind the title bar so your UI fills the full window height.              |
| `macosDisallowHidpi`             | `boolean` | Disable HiDPI/Retina mode and render at 1× pixel density.                                          |
| `macosHasShadow`                 | `boolean` | Control whether the window casts a drop shadow. Defaults to `true`.                                |
| `macosTabbingIdentifier`         | `string`  | Group windows into a native macOS tab bar when they share the same identifier string.              |

```js theme={null}
import { Application } from '@webviewjs/webview';

const app = new Application();

app.whenReady().then(() => {
  const win = app.createBrowserWindow({
    title: 'My App',
    macosTitlebarTransparent: true,
    macosFullsizeContentView: true,
    macosTitlebarButtonsHidden: false,
    macosHasShadow: true,
    macosTabbingIdentifier: 'com.myapp.main',
  });

  win.createWebview({ url: 'app://localhost/index.html' });
});
```

## macOS runtime methods

### Simple fullscreen (pre-Lion style)

macOS introduced a slide-in fullscreen mode in Lion (10.7). The older "simple" fullscreen expands the window to fill the screen without a separate Space:

```js theme={null}
// Check current state
const isSimple = win.simpleFullscreen(); // boolean

// Enter or exit simple fullscreen
win.setSimpleFullscreen(true);
win.setSimpleFullscreen(false);
```

Use `win.setFullscreen(FullscreenType.Borderless)` for the modern macOS fullscreen Space instead.

### Window shadow

```js theme={null}
// Read the current shadow state
const hasShadow = win.hasShadow(); // boolean

// Enable or disable the drop shadow
win.setHasShadow(true);
win.setHasShadow(false);
```

### Native window tabs

macOS can merge multiple windows of the same app into a tab bar when they share a tabbing identifier:

```js theme={null}
// Assign a tabbing identifier at runtime (also available as a creation option)
win.setTabbingIdentifier('com.myapp.editor');

// Read the current identifier
const id = win.tabbingIdentifier(); // string
```

### Document edited state

Set the document-edited flag to display the standard macOS dot in the close button, signalling unsaved changes:

```js theme={null}
// Check the state
const edited = win.isDocumentEdited(); // boolean

// Mark as edited (shows dot in close button)
win.setDocumentEdited(true);

// Clear after saving
win.setDocumentEdited(false);
```

## Menu bar

On macOS the menu bar is a **single, application-level bar** that spans the top of the screen — it belongs to the app, not to any individual window. Set it via `app.setMenu()`:

```js theme={null}
app.setMenu({
  items: [
    {
      label: 'File',
      submenu: {
        items: [
          { id: 'new',  label: 'New',  accelerator: 'CmdOrCtrl+N' },
          { id: 'open', label: 'Open', accelerator: 'CmdOrCtrl+O' },
          { role: 'separator' },
          { role: 'quit' },
        ],
      },
    },
    {
      label: 'Edit',
      submenu: {
        items: [
          { role: 'copy' },
          { role: 'paste' },
          { role: 'cut' },
          { role: 'selectall' },
        ],
      },
    },
  ],
});
```

The application-level menu is ready as soon as `app.setMenu()` returns.

## macOS-specific menu roles

All predefined roles work on macOS. The following roles are macOS-exclusive:

| Role              | Keyboard shortcut | Description                         |
| ----------------- | ----------------- | ----------------------------------- |
| `hide`            | <kbd>⌘H</kbd>     | Hide the front application.         |
| `hideothers`      | <kbd>⌥⌘H</kbd>    | Hide all other applications.        |
| `showall`         | —                 | Unhide all applications.            |
| `services`        | —                 | Insert the system Services submenu. |
| `bringalltofront` | —                 | Bring all app windows to the front. |
| `about`           | —                 | Show the standard About panel.      |

```js theme={null}
{
  label: 'MyApp',
  submenu: {
    items: [
      { role: 'about' },
      { role: 'separator' },
      { role: 'services' },
      { role: 'separator' },
      { role: 'hide' },
      { role: 'hideothers' },
      { role: 'showall' },
      { role: 'separator' },
      { role: 'quit' },
    ],
  },
}
```

## System tray

WebviewJS supports macOS **template icons** — monochrome images that the system automatically adapts to the current Dark or Light menu bar appearance:

```js theme={null}
const tray = app.createTrayIcon({
  id: 'main',
  icon: { data: monochromeRgba, width: 22, height: 22 },
  tooltip: 'My App',
});

// Mark the icon as a template so macOS inverts it automatically
tray.setIconAsTemplate(true);
```

Template icons should be black (or black with alpha). The system handles colour inversion for Dark Mode — you do not need to supply separate assets.
