Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
61 changes: 61 additions & 0 deletions .github/workflows/test-recording.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Test Recording (Linux)

on:
workflow_dispatch:
push:
branches: [ctate/keyboard-overlay]

jobs:
test-recording:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install Chrome dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
fonts-liberation \
libasound2t64 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcups2 \
libdbus-1-3 \
libdrm2 \
libgbm1 \
libgtk-3-0t64 \
libnspr4 \
libnss3 \
libx11-xcb1 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxrandr2 \
xdg-utils

- run: pnpm install --frozen-lockfile

- name: Build
run: |
pnpm --filter @webreel/core build
pnpm --filter webreel build

- name: Record keyboard-shortcuts example
working-directory: examples/keyboard-shortcuts
run: node ../../packages/webreel/dist/index.js record keyboard-shortcuts --verbose --frames

- name: Upload recording artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: recording-output
path: |
examples/keyboard-shortcuts/.webreel/
examples/keyboard-shortcuts/videos/
37 changes: 35 additions & 2 deletions apps/docs/public/schema/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"type": "number",
"minimum": 1,
"description": "Font size in pixels for the keystroke HUD.",
"default": 56
"default": 48
},
"fontFamily": {
"type": "string",
Expand All @@ -153,13 +153,46 @@
"type": "number",
"minimum": 0,
"description": "Border radius in pixels for the keystroke HUD.",
"default": 18
"default": 16
},
"position": {
"type": "string",
"enum": ["top", "bottom"],
"description": "Position of the keystroke HUD.",
"default": "bottom"
},
"blur": {
"type": "number",
"minimum": 0,
"description": "Backdrop blur radius in pixels for the HUD container (live preview only).",
"default": 20
},
"border": {
"type": "string",
"description": "CSS border color for the HUD container."
},
"shadow": {
"type": "string",
"description": "CSS box-shadow for the HUD container."
},
"keyBackground": {
"type": "string",
"description": "CSS background for individual key caps inside the HUD."
},
"keyBorder": {
"type": "string",
"description": "CSS border color for individual key caps inside the HUD."
},
"keyBorderRadius": {
"type": "number",
"minimum": 0,
"description": "Border radius in pixels for individual key caps.",
"default": 10
},
"keyPadding": {
"type": "string",
"description": "CSS padding for individual key caps (e.g. \"8px 16px\").",
"default": "8px 16px"
}
},
"additionalProperties": false
Expand Down
64 changes: 61 additions & 3 deletions apps/docs/src/app/configuration/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -480,12 +480,15 @@ Customize the cursor and keystroke overlay appearance. Can be set at the top lev
"hotspot": "top-left"
},
"hud": {
"background": "rgba(0,0,0,0.7)",
"color": "white",
"fontSize": 48,
"fontFamily": "monospace",
"borderRadius": 12,
"position": "bottom"
"position": "bottom",
"blur": 20,
"keyBackground": "rgba(22, 22, 22, 0.65)",
"keyBorder": "rgba(255, 255, 255, 0.12)",
"keyBorderRadius": 12,
"keyPadding": "10px 20px"
}
}
}
Expand Down Expand Up @@ -590,6 +593,61 @@ Customize the cursor and keystroke overlay appearance. Can be set at the top lev
Where the HUD appears: <code>"top"</code> or <code>"bottom"</code>
</td>
</tr>
<tr>
<td>
<code>blur</code>
</td>
<td>
<code>20</code>
</td>
<td>Backdrop blur radius in pixels for the HUD container (live preview only)</td>
</tr>
<tr>
<td>
<code>border</code>
</td>
<td>-</td>
<td>CSS border color for the HUD container</td>
</tr>
<tr>
<td>
<code>shadow</code>
</td>
<td>-</td>
<td>CSS box-shadow for the HUD container</td>
</tr>
<tr>
<td>
<code>keyBackground</code>
</td>
<td>-</td>
<td>CSS background for individual key caps inside the HUD</td>
</tr>
<tr>
<td>
<code>keyBorder</code>
</td>
<td>-</td>
<td>CSS border color for individual key caps</td>
</tr>
<tr>
<td>
<code>keyBorderRadius</code>
</td>
<td>
<code>10</code>
</td>
<td>Border radius in pixels for individual key caps</td>
</tr>
<tr>
<td>
<code>keyPadding</code>
</td>
<td>
<code>"8px 16px"</code>
</td>
<td>CSS padding for individual key caps</td>
</tr>
</tbody>
</table>

Expand Down
4 changes: 2 additions & 2 deletions examples/custom-theme/videos/custom-theme.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/custom-theme/videos/custom-theme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/drag-and-drop/videos/drag-and-drop.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/drag-and-drop/videos/drag-and-drop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/gif-output/videos/gif-output.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/gif-output/videos/gif-output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/hello-world/videos/hello-world.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/hello-world/videos/hello-world.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/keyboard-shortcuts/videos/keyboard-shortcuts.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/keyboard-shortcuts/videos/keyboard-shortcuts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/keyboard-shortcuts/webreel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"steps": [
{ "action": "pause", "ms": 500 },
{ "action": "click", "selector": ".editor" },
{ "action": "key", "key": "cmd+a" },
{ "action": "key", "key": "shift+a" },
{ "action": "key", "key": "cmd+b", "delay": 800 },
{ "action": "click", "selector": ".editor p:first-of-type" },
{ "action": "key", "key": "cmd+s", "delay": 1200 },
Expand Down
4 changes: 2 additions & 2 deletions examples/mobile-viewport/videos/mobile-viewport.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/mobile-viewport/videos/mobile-viewport.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/modifier-clicks/videos/modifier-clicks.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/modifier-clicks/videos/modifier-clicks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/multi-demo/videos/homepage.mp4
Git LFS file not shown
4 changes: 2 additions & 2 deletions examples/multi-demo/videos/homepage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 44 additions & 12 deletions packages/@webreel/core/src/__tests__/overlays.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,33 +46,52 @@ describe("injectOverlays", () => {
expect(calls[0].expression).toContain("margin-top:-16px");
});

it("uses default HUD theme values when not overridden", async () => {
const { client, calls } = createMockClient();
await injectOverlays(client);
const expr = calls[0].expression;
expect(expr).toContain(`background:${DEFAULT_HUD_THEME.background}`);
expect(expr).toContain(`border-radius:" + z(${DEFAULT_HUD_THEME.borderRadius})`);
});

it("uses custom HUD theme values", async () => {
const { client, calls } = createMockClient();
const theme: OverlayTheme = {
hud: {
background: "red",
color: "blue",
fontSize: 32,
borderRadius: 8,
position: "top",
},
};
await injectOverlays(client, theme);
const expr = calls[0].expression;
expect(expr).toContain("background:red");
expect(expr).toContain("color: blue");
expect(expr).toContain('border-radius:" + z(8)');
expect(expr).toContain('"top:"');
});

it("applies backdrop-filter blur on key caps", async () => {
const { client, calls } = createMockClient();
await injectOverlays(client);
const expr = calls[0].expression;
expect(expr).toContain(`backdrop-filter: blur(${DEFAULT_HUD_THEME.blur}px)`);
expect(expr).toContain(`-webkit-backdrop-filter: blur(${DEFAULT_HUD_THEME.blur}px)`);
});

it("styles key caps with background and border", async () => {
const { client, calls } = createMockClient();
await injectOverlays(client);
const expr = calls[0].expression;
expect(expr).toContain(`background: ${DEFAULT_HUD_THEME.keyBackground}`);
expect(expr).toContain(`border: 1px solid ${DEFAULT_HUD_THEME.keyBorder}`);
expect(expr).toContain("box-shadow:");
});

it("container has no background (transparent layout wrapper)", async () => {
const { client, calls } = createMockClient();
await injectOverlays(client);
const expr = calls[0].expression;
expect(expr).not.toMatch(/keys\.style\.cssText[^;]*background:/);
});

it("includes transition for smooth animation", async () => {
const { client, calls } = createMockClient();
await injectOverlays(client);
const expr = calls[0].expression;
expect(expr).toContain("transition:opacity 0.2s ease,transform 0.2s ease");
});

it("uses custom cursor SVG", async () => {
const { client, calls } = createMockClient();
const svg = '<svg><circle r="10"/></svg>';
Expand Down Expand Up @@ -111,6 +130,13 @@ describe("showKeys", () => {
expect(expr).toContain("&lt;");
expect(expr).toContain("&gt;");
});

it("sets transform to visible position on show", async () => {
const { client, calls } = createMockClient();
await showKeys(client, ["A"]);
const expr = calls[0].expression;
expect(expr).toContain("translateX(-50%) translateY(0)");
});
});

describe("hideKeys", () => {
Expand All @@ -119,4 +145,10 @@ describe("hideKeys", () => {
await hideKeys(client);
expect(calls[0].expression).toContain('opacity = "0"');
});

it("sets transform to offset position on hide", async () => {
const { client, calls } = createMockClient();
await hideKeys(client);
expect(calls[0].expression).toContain("translateX(-50%) translateY(8px)");
});
});
Loading
Loading