docs: add comprehensive WebView widget documentation (beta)#17
docs: add comprehensive WebView widget documentation (beta)#17developersharif merged 1 commit intomainfrom
Conversation
developersharif
commented
Apr 1, 2026
- Add docs/WebView.md with full API reference, examples, JS bridge API, platform notes, error handling, debug mode, and size hints
- Update sidebar with WebView section flagged as Beta
- Update architecture.md with WebView helper process model, IPC protocol, and comparison table vs Tcl/Tk widgets
- Add docs/WebView.md with full API reference, examples, JS bridge API, platform notes, error handling, debug mode, and size hints - Update sidebar with WebView section flagged as Beta - Update architecture.md with WebView helper process model, IPC protocol, and comparison table vs Tcl/Tk widgets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the WebView widget (Beta), enabling the creation of desktop applications with HTML/CSS/JS frontends and PHP backends through a native helper process and JSON-over-stdio IPC. The documentation includes architectural details, API references, and integration examples. Review feedback highlights a variable scoping error in the PHP integration example, a potential XSS vulnerability in the JavaScript rendering logic, the absence of defined class constants for window size hints, and inconsistent build path instructions across the documentation files.
| $app = new Application(); | ||
|
|
||
| // Native Tk window | ||
| $win = new \PhpGui\Widget\Window(['title' => 'Control Panel']); | ||
| $btn = new \PhpGui\Widget\Button($win->getId(), [ | ||
| 'text' => 'Send to WebView', | ||
| 'command' => fn() => $wv->emit('message', 'Hello from Tk!'), | ||
| ]); | ||
| $btn->pack(); | ||
|
|
||
| // WebView window | ||
| $wv = new WebView(['title' => 'Web Frontend']); | ||
| $wv->setHtml('<h1>Waiting...</h1> | ||
| <script>onPhpEvent("message", m => document.querySelector("h1").textContent = m);</script> | ||
| '); | ||
|
|
||
| $app->addWebView($wv); | ||
| $app->run(); |
There was a problem hiding this comment.
The variable $wv is used in the arrow function on line 299 before it is defined on line 304. In PHP, arrow functions capture variables by value at the time of definition. Since $wv is not yet defined when the button is created, this will result in an error when the command is executed. You should define the WebView instance before creating widgets that reference it.
| $app = new Application(); | |
| // Native Tk window | |
| $win = new \PhpGui\Widget\Window(['title' => 'Control Panel']); | |
| $btn = new \PhpGui\Widget\Button($win->getId(), [ | |
| 'text' => 'Send to WebView', | |
| 'command' => fn() => $wv->emit('message', 'Hello from Tk!'), | |
| ]); | |
| $btn->pack(); | |
| // WebView window | |
| $wv = new WebView(['title' => 'Web Frontend']); | |
| $wv->setHtml('<h1>Waiting...</h1> | |
| <script>onPhpEvent("message", m => document.querySelector("h1").textContent = m);</script> | |
| '); | |
| $app->addWebView($wv); | |
| $app->run(); | |
| $app = new Application(); | |
| // WebView window | |
| $wv = new WebView(['title' => 'Web Frontend']); | |
| $wv->setHtml('<h1>Waiting...</h1> | |
| <script>onPhpEvent("message", m => document.querySelector("h1").textContent = m);</script> | |
| '); | |
| // Native Tk window | |
| $win = new \PhpGui\Widget\Window(['title' => 'Control Panel']); | |
| $btn = new \PhpGui\Widget\Button($win->getId(), [ | |
| 'text' => 'Send to WebView', | |
| 'command' => fn() => $wv->emit('message', 'Hello from Tk!'), | |
| ]); | |
| $btn->pack(); | |
| $app->addWebView($wv); | |
| $app->run(); |
| function render(todos) { | ||
| const list = document.getElementById("list"); | ||
| list.innerHTML = todos.map(t => | ||
| `<li onclick="invoke(\'toggleTodo\', \'${t.id}\')" | ||
| style="${t.completed ? \'text-decoration:line-through\' : \'\'}"> | ||
| ${t.text} | ||
| </li>` | ||
| ).join(""); | ||
| } |
There was a problem hiding this comment.
The example uses innerHTML with template literals to render todo items, which is vulnerable to Cross-Site Scripting (XSS) if the todo text contains malicious HTML. It is safer to use textContent and createElement to build the list items.
| function render(todos) { | |
| const list = document.getElementById("list"); | |
| list.innerHTML = todos.map(t => | |
| `<li onclick="invoke(\'toggleTodo\', \'${t.id}\')" | |
| style="${t.completed ? \'text-decoration:line-through\' : \'\'}"> | |
| ${t.text} | |
| </li>` | |
| ).join(""); | |
| } | |
| function render(todos) { | |
| const list = document.getElementById("list"); | |
| list.innerHTML = ""; | |
| todos.forEach(t => { | |
| const li = document.createElement("li"); | |
| li.textContent = t.text; | |
| li.style.textDecoration = t.completed ? "line-through" : ""; | |
| li.onclick = () => invoke("toggleTodo", t.id); | |
| list.appendChild(li); | |
| }); | |
| } |
| | Value | Constant | Behavior | | ||
| |-------|----------|-------------------------------------------------| | ||
| | `0` | NONE | Default — user can resize freely | | ||
| | `1` | MIN | Sets minimum size | | ||
| | `2` | MAX | Sets maximum size | | ||
| | `3` | FIXED | Fixed size — user cannot resize | |
There was a problem hiding this comment.
The table mentions constants like NONE, MIN, MAX, and FIXED, but these are not currently defined in the WebView class. Users are forced to use magic numbers (0-3). It is recommended to define these as class constants (e.g., WebView::SIZE_HINT_FIXED) to improve maintainability and ensure the code aligns with the documentation.
| | macOS Intel | `webview_helper_darwin_x86_64` | | ||
| | Windows x64 | `webview_helper_windows_x86_64.exe` | | ||
|
|
||
| If auto-download fails, build from source: `cd src/lib/webview_helper && bash build.sh` |
There was a problem hiding this comment.
The build path cd src/lib/webview_helper is inconsistent with the path provided in docs/WebView.md (cd vendor/developersharif/php-gui/src/lib/webview_helper). For users who installed the library via Composer, the latter is correct. It would be better to provide a consistent instruction or clarify the context (e.g., contributor vs. user).