Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
eb31d3a
Initial scaffold of Toolbar
josephfusco Oct 8, 2025
5dc66c0
feat(toolbar): Add real WordPress integration to demo
josephfusco Oct 8, 2025
1fe19eb
Clean up toolbar demo
josephfusco Oct 8, 2025
9465c96
Modern state management following TanStack/Zustand patterns. Minimal …
josephfusco Oct 9, 2025
10bcabf
Add centralized templates and shared port calculation
josephfusco Oct 9, 2025
03d58ba
feat(toolbar): configure vanilla example to use template-based genera…
josephfusco Oct 9, 2025
f97b6a6
feat(toolbar): add Next.js toolbar demo example
josephfusco Oct 9, 2025
cd31d75
feat(toolbar): Add configurable positioning and theming
josephfusco Oct 9, 2025
e16a6f5
feat(plugins): Add modular headless WordPress plugins
josephfusco Oct 9, 2025
f3a4895
refactor(examples): Use production WordPress URL pattern with modular…
josephfusco Oct 9, 2025
481c20f
fix(examples): Use absolute paths for plugin references in wp-env
josephfusco Oct 9, 2025
4f090de
fix(examples): Ensure WordPress and frontend start concurrently
josephfusco Oct 9, 2025
7fcf1a8
chore(examples): Remove obsolete mu-plugin infrastructure and improve…
josephfusco Oct 9, 2025
79cbe0f
Support multiple frontend URLs in admin links
josephfusco Oct 9, 2025
5236d39
Update wordpress.ts
josephfusco Oct 9, 2025
316fb36
Update scripts/get-ports.js
josephfusco Oct 9, 2025
a3d62a2
feat(plugins): add composer.json and standardize versions to 0.1.0
josephfusco Oct 9, 2025
bd694fa
feat(toolbar): add demo path indicator and use JSDoc comments
josephfusco Oct 9, 2025
eca9b26
docs: add CHANGELOG.md files for initial 0.1.0 release
josephfusco Oct 9, 2025
d64b0ff
Add standard badges
josephfusco Oct 9, 2025
310cff1
fix(hwp-cors-local): add WP_DEBUG check to match documentation
josephfusco Oct 9, 2025
144dfbe
feat(toolbar): add comprehensive CSS custom properties for theming
josephfusco Oct 9, 2025
b7c98dd
fix(toolbar-demo): use type-safe getConfig() method
josephfusco Oct 9, 2025
906e6f6
docs(hwp-frontend-links): document multiple frontends support
josephfusco Oct 9, 2025
d9baa74
feat(toolbar-demo): improve error handling with specific messages
josephfusco Oct 9, 2025
5f2c6ba
docs(get-ports): add detailed port calculation documentation
josephfusco Oct 9, 2025
63724bc
feat(toolbar): add comprehensive dropdown accessibility
josephfusco Oct 10, 2025
90a96d8
fix(toolbar-demo): properly handle node positioning in sections
josephfusco Oct 10, 2025
cb03ad7
chore(toolbar-demo): remove unused demo-path node
josephfusco Oct 10, 2025
74449b0
refactor: convert toolbar package from TypeScript to vanilla JavaScript
josephfusco Oct 10, 2025
7ef2646
toolbar position
josephfusco Oct 10, 2025
78d6eb4
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
c3a20f5
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
8fedd1a
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
65bdaa9
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
1e65d15
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
085b439
feat(toolbar): improve WordPress connection error handling
josephfusco Oct 10, 2025
218c386
Refactor toolbar demo setup and update configs
colinmurphy Oct 16, 2025
be0c467
Refactor Next.js toolbar demo setup and docs
colinmurphy Oct 16, 2025
02b3807
Update packages/toolbar/src/core/VanillaRenderer.js
theodesp Oct 16, 2025
7aed656
Move example projects to packages/toolbar/examples
colinmurphy Oct 16, 2025
5f2aa1b
Fix for next example.
colinmurphy Oct 16, 2025
712bf6a
update readme
ahuseyn Oct 17, 2025
a5ada57
fix(toolbar): update example readmes, add htaccess to fix wp-env issues
ahuseyn Oct 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ node_modules

# Build outputs
dist
build
.next
out

# Testing
coverage
Expand All @@ -13,6 +16,7 @@ test-results/
# WordPress
.wp-env
.wp-env.override.json
wp-env/
uploads/
debug.log
__MACOSX
Expand All @@ -29,4 +33,6 @@ __MACOSX
## Examples
examples/**/package-lock.json
examples/**/__MACOSX
examples/**/mu-plugin.php
examples/**/.wp-env.json
``
11 changes: 11 additions & 0 deletions examples/next/toolbar-demo/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
5 changes: 5 additions & 0 deletions packages/toolbar/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
node_modules
*.log
.DS_Store
*.tsbuildinfo
22 changes: 22 additions & 0 deletions packages/toolbar/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2025-01-09

### Added
- Initial release of @wpengine/hwp-toolbar
- Framework-agnostic core toolbar with modern state management
- React adapter with hooks (useToolbar, useToolbarState, useWordPressContext)
- Vanilla JavaScript renderer for non-React applications
- WordPress context management with separate API (setWordPressContext)
- Plugin system via register() method for custom toolbar nodes
- Configurable positioning (top/bottom) and theming (light/dark/auto)
- Minimal base styles for full developer control
- TypeScript support with complete type definitions
- CSS exports for styling integration

[0.1.0]: https://github.com/wpengine/hwptoolkit/releases/tag/toolbar-v0.1.0
277 changes: 277 additions & 0 deletions packages/toolbar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
# @wpengine/hwp-toolbar

> Framework-agnostic toolbar for headless WordPress applications

A lightweight, performant toolbar for headless WordPress. Works with any JavaScript framework or vanilla JS.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Example Projects](#example-projects)
- [Vanilla JavaScript](#vanilla-javascript)
- [React (Recommended)](#react-recommended)
- [Core API](#core-api)
- [Toolbar Class](#toolbar-class)
- [Renderers](#renderers)
- [Styling](#styling)
- [React Hooks API](#react-hooks-api)
- [`useToolbar(toolbar)`](#usetoolbartoolbar)
- [`useToolbarState(toolbar)`](#usetoolbarstatetoolbar)
- [`useToolbarNodes(toolbar)`](#usetoolbarnodestoolbar)
- [Framework Examples](#framework-examples)
- [Vue](#vue)
- [Vanilla JavaScript](#vanilla-javascript-1)
- [TypeScript](#typescript)
- [Development](#development)
- [License](#license)


## Features

- **Framework Agnostic** - Works with React, Vue, Svelte, or vanilla JavaScript
- **Zero Dependencies** - Core library has no dependencies
- **React Hooks** - First-class React support with hooks
- **Headless UI** - Full control over rendering and styling

## Installation

```bash
npm install @wpengine/hwp-toolbar
```

## Quick Start

### Example Projects

Check out the complete example projects in the `examples/` directory:

- **Next.js**: `examples/next/` - Full Next.js application with Apollo GraphQL integration
- **Vanilla JavaScript**: `examples/vanilla/` - Pure JavaScript implementation with demo HTML

Each example includes setup instructions and demonstrates different integration patterns.

### Vanilla JavaScript

```javascript
import { Toolbar, VanillaRenderer } from "@wpengine/hwp-toolbar";
import "@wpengine/hwp-toolbar/styles";

const toolbar = new Toolbar({
onPreviewChange: (enabled) => {
console.log("Preview mode:", enabled);
},
});

toolbar.setWordPressContext({
user: { id: 1, name: "Admin" },
site: { url: "https://example.com", adminUrl: "https://example.com/wp-admin" },
post: { id: 123, title: "Hello World", type: "post", status: "draft", slug: "hello-world" },
});

const renderer = new VanillaRenderer(toolbar, "toolbar");
```

### React (Recommended)

```tsx
import { Toolbar } from "@wpengine/hwp-toolbar";
import { useToolbar } from "@wpengine/hwp-toolbar/react";

const toolbar = new Toolbar({
onPreviewChange: (enabled) => {
console.log("Preview mode:", enabled);
},
});

function MyToolbar() {
const { state, nodes } = useToolbar(toolbar);

return (
<div className='toolbar'>
{nodes.map((node) => (
<button key={node.id} onClick={node.onClick}>
{typeof node.label === "function" ? node.label() : node.label}
</button>
))}
{state.user && <span>User: {state.user.name}</span>}
</div>
);
}
```

## API

### Toolbar

**Constructor**

```javascript
new Toolbar(config?)
```

**Config:**

- `onPreviewChange?: (enabled: boolean) => void` - Preview toggle callback

**Methods:**

```javascript
// Register a node
toolbar.register(id, label, onClick?)
toolbar.register('help', 'Help', () => window.open('/help'))

// Update state
toolbar.setState({ user, post, site, preview })

// Set WordPress context (helper)
toolbar.setWordPressContext({ user, post, site })

// Subscribe to changes
const unsubscribe = toolbar.subscribe((nodes, state) => {
console.log('State changed:', state);
})

// Cleanup
toolbar.destroy()
```

### VanillaRenderer

```javascript
const renderer = new VanillaRenderer(toolbar, "element-id");
// or
const renderer = new VanillaRenderer(toolbar, document.getElementById("toolbar"));

// Cleanup
renderer.destroy();
```

## Default Nodes

The toolbar includes three built-in nodes:

- **Edit Post** - Opens WordPress editor (visible when post + user)
- **WP Admin** - Dashboard link (visible when user exists)
- **Preview** - Toggle preview mode (visible when post or user)

## Styling

Import the base styles:

```javascript
import "@wpengine/hwp-toolbar/styles";
```

### Customization

Override CSS custom properties:

```css
:root {
--hwp-toolbar-bg: #1a1a1a;
--hwp-toolbar-primary: #00a0d2;
}
```

## React Hooks API

### `useToolbar(toolbar)`

Returns both state and nodes in a single hook:

```tsx
import { useToolbar } from "@wpengine/hwp-toolbar/react";

function MyToolbar() {
const { state, nodes } = useToolbar(toolbar);
// Full control over rendering
}
```

### `useToolbarState(toolbar)`

Subscribe to toolbar state only:

```tsx
import { useToolbarState } from "@wpengine/hwp-toolbar/react";

function UserDisplay() {
const state = useToolbarState(toolbar);
return <div>{state.user?.name}</div>;
}
```

### `useToolbarNodes(toolbar)`

Subscribe to visible nodes only:

```tsx
import { useToolbarNodes } from "@wpengine/hwp-toolbar/react";

function ToolbarButtons() {
const nodes = useToolbarNodes(toolbar);
return (
<>
{nodes.map((node) => (
<button key={node.id} onClick={node.onClick}>
{typeof node.label === "function" ? node.label() : node.label}
</button>
))}
</>
);
}
```

## Framework Examples

### Vue

```vue
<template>
<div ref="toolbarRef" />
</template>

<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import { Toolbar, VanillaRenderer } from "@wpengine/hwp-toolbar";

const toolbarRef = ref(null);
let toolbar, renderer;

onMounted(() => {
toolbar = new Toolbar();
renderer = new VanillaRenderer(toolbar, toolbarRef.value);
});

onUnmounted(() => {
renderer?.destroy();
toolbar?.destroy();
});
</script>
```

### Vanilla JavaScript

See `demo.html` for a complete example.

## Development

```bash
# Build
npm run build

# Watch mode
npm run dev

# Clean
npm run clean

# View demo
open demo.html
```

## License

BSD-2-Clause
25 changes: 25 additions & 0 deletions packages/toolbar/examples/next/.wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"phpVersion": "8.4",
"plugins": [
"https://github.com/wp-graphql/wp-graphql/releases/latest/download/wp-graphql.zip",
"../plugins/hwp-cors-local",
"../plugins/hwp-frontend-links",
"../plugins/hwp-wp-env-helpers"
],
"config": {
"WP_DEBUG": true,
"SCRIPT_DEBUG": false,
"GRAPHQL_DEBUG": true,
"WP_DEBUG_LOG": true,
"WP_DEBUG_DISPLAY": false,
"SAVEQUERIES": false,
"WP_HOME": "http://localhost:8888",
"HEADLESS_FRONTEND_URL": "http://localhost:3000"
},
"mappings": {
".htaccess": "./wp-env/setup/.htaccess"
},
"lifecycleScripts": {
"afterStart": "wp-env run cli -- wp theme activate twentytwentyfour && wp-env run cli -- wp rewrite structure '/%postname%/' && wp-env run cli -- wp rewrite flush"
}
}
Loading