Skip to content
Merged
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 5 additions & 7 deletions docs/source/forge/sparks/lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ Controls the appearance of the PIN / passphrase entry dialog shown when a lock e

| Value | Effect |
|---|---|
| `action: element_tap` | Fires the forged element's `tap_action`. |
| `action: element_hold` | Fires the forged element's `hold_action`. |
| `action: element_double_tap` | Fires the forged element's `double_tap_action`. |
| `action: element_tap` | Fires the target element's `tap_action`. |
| `action: element_hold` | Fires the target element's `hold_action`. |
| `action: element_double_tap` | Fires the target element's `double_tap_action`. |
| Any HA action object | Dispatches that action against `entity` (e.g. `action: toggle`). |

### Lock entry keys
Expand Down Expand Up @@ -385,20 +385,18 @@ forge:
sparks:
- type: lock
for: hui-tile-card $ ha-tile-icon
icon_locked_color: white
icon_unlocked_color: white
icon_unlocked: mdi:lock-open-outline
duration: 5s
locks:
- code: 1234
admins: true
uix:
style: |
:host {
--uix-lock-opacity: 1;
--uix-lock-icon-color: white;
--uix-lock-icon-background: red;
--uix-lock-icon-background-unlocked: green;
--uix-lock-icon-border-radius: 50%;
--uix-lock-icon-padding: 1px;
}
element:
type: tile
Expand Down
30 changes: 29 additions & 1 deletion src/forge/sparks/lock-target-adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
* 2. Add a `case` for the element's tag name in `getLockTargetAdapter`.
*/

/** Pixel offsets used as the default icon position for a target element type. */
export interface AdapterIconPosition {
top?: string;
bottom?: string;
left?: string;
right?: string;
}

export interface LockTargetAdapter {
/** Called when the lock becomes active (element should be blocked). */
lock(element: HTMLElement, overlay: HTMLElement): void;
Expand All @@ -16,6 +24,12 @@ export interface LockTargetAdapter {
cleanup(element: HTMLElement): void;
/** Returns the default lock-icon size for this target element type. */
defaultIconSize(): string;
/** Returns the default lock-icon padding for this target element type, or `null` for no override. */
defaultIconPadding(): string | null;
/** Returns the default lock-icon border-radius for this target element type, or `null` for no override. */
defaultIconBorderRadius(): string | null;
/** Returns the default lock-icon position for this target element type, or `null` for no override. */
defaultIconPosition(): AdapterIconPosition | null;
}

/**
Expand Down Expand Up @@ -166,7 +180,21 @@ class HaTileIconLockAdapter implements LockTargetAdapter {
}

defaultIconSize(): string {
return "18px";
// ha-tile-icon is a compact element; 12px fits neatly in its corner.
return "12px";
}

defaultIconPadding(): string | null {
return "2px";
}

defaultIconBorderRadius(): string | null {
return "50%";
}

defaultIconPosition(): AdapterIconPosition | null {
// Position the icon at the top-left corner of ha-tile-icon.
return { top: "3px", left: "3px" };
}

private _removeCapture(element: HTMLElement): void {
Expand Down
27 changes: 19 additions & 8 deletions src/forge/sparks/uix-spark-lock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class UixForgeSparkLock extends UixForgeSparkBase {
private _getEffectiveIconPosition(): IconPosition | null {
if (this._iconPosition !== null) return this._iconPosition;
if (this.controller.forge.mold?.isRow()) return { top: "6px", left: "30px" };
if (this._targetAdapter) return this._targetAdapter.defaultIconPosition();
return null;
}

Expand Down Expand Up @@ -370,10 +371,6 @@ export class UixForgeSparkLock extends UixForgeSparkBase {
// would be visible during the fade. Only apply the unlocked colour when
// actually swapping to a new icon.
const customColor = fadeOut ? this._iconLockedColor : (this._isUnlocked ? this._iconUnlockedColor : this._iconLockedColor);
const defaultColor = (this._isUnlocked && !fadeOut)
// Material Design green/red used as fallbacks when HA theme variables are unavailable
? "var(--success-color, #43a047)"
: "var(--error-color, #db4437)";

if (this._iconElement) {
this._iconElement.icon = icon;
Expand All @@ -385,10 +382,24 @@ export class UixForgeSparkLock extends UixForgeSparkBase {
? "var(--uix-lock-icon-background-blocked, var(--uix-lock-icon-background, none))"
: "var(--uix-lock-icon-background, none)";
this._iconElement.style.setProperty("background", iconBg);
this._iconElement.style.setProperty("border-radius", "var(--uix-lock-icon-border-radius, none)");
this._iconElement.style.setProperty("padding", "var(--uix-lock-icon-padding, 0)");
const defaultBorderRadius = this._targetAdapter?.defaultIconBorderRadius() ?? "none";
this._iconElement.style.setProperty("border-radius", `var(--uix-lock-icon-border-radius, ${defaultBorderRadius})`);
const defaultPadding = this._targetAdapter?.defaultIconPadding() ?? "0";
this._iconElement.style.setProperty("padding", `var(--uix-lock-icon-padding, ${defaultPadding})`);
this._iconElement.style.setProperty("line-height", "normal");
this._iconElement.style.setProperty("color", customColor || defaultColor);
// Resolve icon colour: config-supplied value takes highest precedence, then
// state-specific CSS vars, then a general override var, then HA theme defaults.
let colorValue: string;
if (customColor) {
colorValue = customColor;
} else if (this._isUnlocked && !fadeOut) {
colorValue = "var(--uix-lock-icon-unlocked-color, var(--uix-lock-icon-color, var(--success-color, #43a047)))";
} else if (isBlocked) {
colorValue = "var(--uix-lock-icon-blocked-color, var(--uix-lock-icon-color, var(--error-color, #db4437)))";
} else {
colorValue = "var(--uix-lock-icon-locked-color, var(--uix-lock-icon-color, var(--error-color, #db4437)))";
}
this._iconElement.style.setProperty("color", colorValue);
// When fading the lock icon out (no icon_unlocked configured) use the
// CSS-var-controlled duration (default 2s). When swapping to an explicit
// unlocked icon, keep the fast 0.25s swap transition.
Expand All @@ -398,7 +409,7 @@ export class UixForgeSparkLock extends UixForgeSparkBase {
this._iconElement.style.setProperty("transition", `color 0.25s ease, opacity ${opacityDuration} ease`);
this._iconElement.style.setProperty("opacity", fadeOut ? "0" : "1");
// Allow CSS-var-based positional override independent of config-based offset.
this._iconElement.style.setProperty("display", "inline-block");
this._iconElement.style.setProperty("display", "inline-flex");
this._iconElement.style.setProperty("translate", `var(--uix-lock-icon-position, none)`);

// ── Icon position ─────────────────────────────────────────────────────
Expand Down
Loading