From 12d27a1bff26765b4009e596e161fbdb258988c8 Mon Sep 17 00:00:00 2001 From: Dustin Swan Date: Tue, 3 Feb 2026 14:28:39 -0700 Subject: [PATCH] Adding Opacity ui primitive --- src/types.ts | 1 + src/ui.ts | 8 ++++++++ src/valueToUI.ts | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/src/types.ts b/src/types.ts index c4aa396..8ae84a9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -53,6 +53,7 @@ export type UIValue = | { kind: 'column', children: UIValue[], gap: number } | { kind: 'clickable', child: UIValue, event: Value } | { kind: 'padding', child: UIValue, amount: number } + | { kind: 'opacity', child: UIValue, opacity: number } | { kind: 'stack', children: UIValue[] } | { kind: 'text-input', value: string, placeholder: string, x: number, y: number, w: number, h: number, focused: boolean, onInput: Value, onSubmit: Value } diff --git a/src/ui.ts b/src/ui.ts index eec323b..5880778 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -98,6 +98,14 @@ function renderUI(ui: UIValue, ctx: CanvasRenderingContext2D, x: number, y: numb renderUI(ui.child, ctx, x + ui.amount, y + ui.amount); break; + case 'opacity': { + const previousAlpha = ctx.globalAlpha; + ctx.globalAlpha = previousAlpha * ui.opacity; + renderUI(ui.child, ctx, x, y); + ctx.globalAlpha = previousAlpha; + break; + } + case 'stack': { for (const child of ui.children) { renderUI(child, ctx, x, y); diff --git a/src/valueToUI.ts b/src/valueToUI.ts index 2be6c4a..f9a56a6 100644 --- a/src/valueToUI.ts +++ b/src/valueToUI.ts @@ -77,6 +77,15 @@ export function valueToUI(value: Value): UIValue { return { kind: 'padding', amount: amount.value, child: valueToUI(child) }; } + case 'Opacity': { + const { child, opacity } = fields; + + if (opacity.kind !== 'int') + throw new Error('Invalid Opacity fields'); + + return { kind: 'opacity', opacity: opacity.value, child: valueToUI(child) }; + } + case 'Stack': { const children = fields.children;