Skip to content

Commit 5d9ac35

Browse files
committed
feat(live): add live UI helpers
1 parent bb7a96b commit 5d9ac35

27 files changed

Lines changed: 4795 additions & 18 deletions

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ endif()
1212
set_property(GLOBAL PROPERTY VIX_UI_MODULE_ALREADY_INCLUDED TRUE)
1313

1414
project(ui
15-
VERSION 0.2.0
15+
VERSION 0.5.0
1616
DESCRIPTION "Web-first UI and app shell primitives for Vix.cpp applications"
1717
LANGUAGES CXX
1818
)
@@ -143,6 +143,11 @@ set(UI_SOURCES
143143
src/forms/Field.cpp
144144
src/forms/Form.cpp
145145

146+
src/live/Fragment.cpp
147+
src/live/LiveUpdate.cpp
148+
src/live/FlashMessage.cpp
149+
src/live/Toast.cpp
150+
146151
src/platform/Platform.cpp
147152

148153
src/shell/ShellConfig.cpp

README.md

Lines changed: 178 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,34 @@
33
Web-first UI and app shell primitives for Vix.cpp applications.
44

55
`vix::ui` is a small UI foundation layer built on top of the Vix template engine.
6-
It helps Vix.cpp applications describe views, render HTML responses, manage assets, build simple forms, and prepare future browser, desktop, and mobile app shells.
6+
It helps Vix.cpp applications describe views, render HTML responses, manage assets, build forms, create live UI fragments, and run server-rendered interfaces inside app shells.
77

88
It is not a replacement for `vix::template_`.
99
It is a higher-level layer that makes template-based web UI development cleaner.
1010

11+
## Version
12+
13+
Current module version:
14+
15+
```txt
16+
0.5.0
17+
```
18+
1119
## Goals
1220

13-
Vix UI starts with a simple direction:
21+
Vix UI follows a simple direction:
1422

1523
- keep Vix web-first
1624
- reuse the existing Vix template engine
1725
- provide small UI primitives
26+
- support server-rendered UI first
1827
- avoid a heavy frontend framework
19-
- prepare desktop/mobile shells without forcing native UI complexity early
28+
- prepare desktop/mobile shells through WebView containers
29+
- make dashboards, admin panels and internal tools easier to build
2030

2131
The first target is server-rendered web UI.
2232

23-
Later, the same web UI foundation can be used by desktop or mobile shells through WebView-based app containers.
33+
The same UI foundation can then be used by desktop or mobile shells through WebView-based app containers.
2434

2535
## What it provides
2636

@@ -39,9 +49,15 @@ Current primitives:
3949
- `vix::ui::Field`
4050
- `vix::ui::Form`
4151
- `vix::ui::ValidationError`
52+
- `vix::ui::Fragment`
53+
- `vix::ui::LiveUpdate`
54+
- `vix::ui::FlashMessage`
55+
- `vix::ui::Toast`
4256
- `vix::ui::Platform`
4357
- `vix::ui::ShellConfig`
4458
- `vix::ui::AppShell`
59+
- `vix::ui::ServerProcess`
60+
- `vix::ui::ServerReadiness`
4561

4662
## Basic view example
4763

@@ -60,8 +76,7 @@ int main()
6076
loader->set(
6177
"home.html",
6278
"<h1>Hello {{ name }}</h1>"
63-
"<p>{{ page_title }}</p>"
64-
);
79+
"<p>{{ page_title }}</p>");
6580

6681
vix::template_::Engine engine(loader);
6782

@@ -93,8 +108,7 @@ attrs.set("class", "card");
93108
std::string html = vix::ui::Html::tag(
94109
"div",
95110
vix::ui::Html::text("Hello <Vix>"),
96-
attrs
97-
);
111+
attrs);
98112
```
99113
100114
Output:
@@ -108,15 +122,17 @@ Output:
108122
```cpp
109123
#include <vix/ui/html/HtmlResponse.hpp>
110124

111-
vix::ui::HtmlResponse response = vix::ui::HtmlResponse::html("<h1>Hello</h1>", 200);
125+
vix::ui::HtmlResponse response =
126+
vix::ui::HtmlResponse::html("<h1>Hello</h1>", 200);
112127

113128
response.header_content_type(); // text/html; charset=utf-8
114129
response.body(); // <h1>Hello</h1>
115130
response.status_code(); // 200
116131
```
117132
118133
`HtmlResponse` is transport-neutral.
119-
It does not depend on a specific HTTP response type. Higher-level Vix integrations can copy its body, status and content type into a real HTTP response.
134+
135+
It does not depend on a specific HTTP response type. Higher-level Vix integrations can copy its body, status, and content type into a real HTTP response.
120136
121137
## Assets
122138
@@ -165,22 +181,120 @@ Validation errors can be attached to the form and to individual fields:
165181
form.add_error("email", "Email is required.");
166182
```
167183

184+
## Live UI fragments
185+
186+
`Fragment` represents a small server-rendered HTML piece.
187+
188+
It can be returned from a route, embedded in a template, or sent through a WebSocket-friendly update payload.
189+
190+
```cpp
191+
#include <vix/ui/live/Fragment.hpp>
192+
193+
vix::ui::Fragment stats =
194+
vix::ui::Fragment::make("dashboard-stats")
195+
.set_target("#stats-card")
196+
.set_html("<strong>128</strong><span>active users</span>");
197+
198+
std::string html = stats.render();
199+
std::string wrapped = stats.render_wrapped();
200+
```
201+
202+
## Live updates
203+
204+
`LiveUpdate` describes how a client should apply a server-rendered fragment.
205+
206+
Supported actions:
207+
208+
- `replace`
209+
- `append`
210+
- `prepend`
211+
- `before`
212+
- `after`
213+
- `remove`
214+
- `none`
215+
216+
```cpp
217+
#include <vix/ui/live/Fragment.hpp>
218+
#include <vix/ui/live/LiveUpdate.hpp>
219+
220+
vix::ui::Fragment row =
221+
vix::ui::Fragment::make("user-row-42")
222+
.set_html("<tr id=\"user-42\"><td>Gaspard</td><td>online</td></tr>");
223+
224+
vix::ui::LiveUpdate update =
225+
vix::ui::LiveUpdate::replace("#user-42", row)
226+
.set_event("users.updated")
227+
.set_id("update-42");
228+
229+
std::string payload = update.to_json();
230+
```
231+
232+
Example payload:
233+
234+
```json
235+
{
236+
"type": "ui.update",
237+
"action": "replace",
238+
"target": "#user-42",
239+
"event": "users.updated",
240+
"id": "update-42",
241+
"fragment": "user-row-42",
242+
"html": "<tr id=\"user-42\"><td>Gaspard</td><td>online</td></tr>"
243+
}
244+
```
245+
246+
## Flash messages
247+
248+
```cpp
249+
#include <vix/ui/live/FlashMessage.hpp>
250+
251+
vix::ui::FlashMessage flash =
252+
vix::ui::FlashMessage::success("Profile updated successfully.")
253+
.set_title("Saved")
254+
.set_dismissible(true);
255+
256+
std::string html = flash.render();
257+
```
258+
259+
## Toasts
260+
261+
```cpp
262+
#include <chrono>
263+
#include <vix/ui/live/Toast.hpp>
264+
265+
vix::ui::Toast toast =
266+
vix::ui::Toast::info("Background sync completed.")
267+
.set_title("Sync")
268+
.set_position(vix::ui::ToastPosition::BottomRight)
269+
.set_timeout(std::chrono::milliseconds(3000));
270+
271+
std::string html = toast.render();
272+
```
273+
168274
## App shell
169275

170-
`AppShell` is currently a lightweight shell descriptor.
276+
`AppShell` is the public shell facade for Vix UI applications.
171277

172-
It stores configuration, validates the shell settings, tracks running/stopped state, and exposes the effective target URL.
278+
It stores configuration, validates shell settings, can start a local server process, wait for server readiness, and open the configured target URL through the selected backend.
173279

174280
```cpp
281+
#include <chrono>
282+
175283
#include <vix/ui/shell/AppShell.hpp>
176284
#include <vix/ui/shell/ShellConfig.hpp>
177285

178286
vix::ui::ShellConfig config;
179287

180288
config.set_name("Vix Admin")
181289
.set_title("Vix Admin")
290+
.set_app_id("com.vix.admin")
291+
.set_app_version("0.5.0")
292+
.set_vendor("Vix.cpp")
182293
.set_host("127.0.0.1")
183294
.set_port(8080)
295+
.set_readiness_url("http://127.0.0.1:8080/health")
296+
.set_startup_timeout(std::chrono::milliseconds(5000))
297+
.set_wait_for_server(true)
184298
.set_width(1280)
185299
.set_height(720);
186300

@@ -190,11 +304,11 @@ auto result = shell.start();
190304

191305
if (result.is_ok())
192306
{
193-
// shell.running() == true
307+
// shell started
194308
}
195309
```
196310
197-
Native desktop/mobile WebView startup can be added later on top of this public surface.
311+
When Linux WebView support is enabled, the Linux backend can open the target URL inside a desktop WebView shell.
198312
199313
## Module structure
200314
@@ -225,9 +339,17 @@ include/vix/ui/
225339
Field.hpp
226340
ValidationError.hpp
227341
342+
live/
343+
Fragment.hpp
344+
LiveUpdate.hpp
345+
FlashMessage.hpp
346+
Toast.hpp
347+
228348
shell/
229349
AppShell.hpp
230350
ShellConfig.hpp
351+
ServerProcess.hpp
352+
ServerReadiness.hpp
231353
232354
platform/
233355
Platform.hpp
@@ -239,7 +361,7 @@ include/vix/ui/
239361

240362
## Build
241363

242-
From the repository root:
364+
From the module directory or repository workflow:
243365

244366
```bash
245367
vix build
@@ -257,6 +379,26 @@ Run examples:
257379
vix run examples/01_basic_view.cpp
258380
vix run examples/02_html_response.cpp
259381
vix run examples/03_assets.cpp
382+
vix run examples/04_forms.cpp
383+
vix run examples/06_fragment.cpp
384+
vix run examples/07_live_update.cpp
385+
vix run examples/08_flash_and_toast.cpp
386+
```
387+
388+
Build benchmarks with CMake:
389+
390+
```bash
391+
vix build --build-target all -v -DUI_BUILD_BENCHMARKS=ON
392+
```
393+
394+
Run benchmarks:
395+
396+
```bash
397+
./build-ninja/benchmarks/ui_html_benchmark
398+
./build-ninja/benchmarks/ui_assets_benchmark
399+
./build-ninja/benchmarks/ui_forms_benchmark
400+
./build-ninja/benchmarks/ui_live_benchmark
401+
./build-ninja/benchmarks/ui_view_context_benchmark
260402
```
261403

262404
## Design direction
@@ -282,10 +424,31 @@ The UI module is responsible for:
282424
- HTML response data
283425
- asset helpers
284426
- form helpers
427+
- live UI fragments
428+
- WebSocket-friendly update payloads
429+
- flash and toast rendering helpers
285430
- platform/app shell primitives
431+
- server readiness helpers
286432

287433
This keeps the architecture simple and avoids building a heavy UI framework too early.
288434

435+
## Non-goals
436+
437+
Vix UI is not trying to be:
438+
439+
- a React clone
440+
- a Flutter clone
441+
- a Qt replacement
442+
- a native widget toolkit
443+
- a complex virtual DOM engine
444+
- a heavy frontend framework
445+
446+
The direction is:
447+
448+
- server-rendered UI first
449+
- WebView app shell later
450+
- native UI only if truly needed
451+
289452
## License
290453

291454
MIT License.

benchmarks/CMakeLists.txt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ============================================================================
2+
# UI benchmarks
3+
# ============================================================================
4+
5+
function(ui_add_benchmark target source)
6+
add_executable(${target}
7+
${source}
8+
)
9+
10+
target_compile_features(${target}
11+
PRIVATE
12+
cxx_std_20
13+
)
14+
15+
target_link_libraries(${target}
16+
PRIVATE
17+
vix::ui
18+
benchmark::benchmark
19+
benchmark::benchmark_main
20+
)
21+
22+
if(VIX_ENABLE_SANITIZERS AND NOT MSVC)
23+
target_compile_options(${target}
24+
PRIVATE
25+
-fno-omit-frame-pointer
26+
-fsanitize=address,undefined
27+
)
28+
29+
target_link_options(${target}
30+
PRIVATE
31+
-fsanitize=address,undefined
32+
)
33+
endif()
34+
endfunction()
35+
36+
ui_add_benchmark(ui_html_benchmark html_benchmark.cpp)
37+
ui_add_benchmark(ui_assets_benchmark assets_benchmark.cpp)
38+
ui_add_benchmark(ui_forms_benchmark forms_benchmark.cpp)
39+
ui_add_benchmark(ui_live_benchmark live_benchmark.cpp)
40+
ui_add_benchmark(ui_view_context_benchmark view_context_benchmark.cpp)

0 commit comments

Comments
 (0)