@sukramj/fabric-ui 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -74,7 +74,14 @@ host's stylesheet, after Tailwind:
74
74
  `.dark` on `<html>` switches the dark tokens; `data-skin="ha"` on `<html>`
75
75
  resolves the tokens from Home Assistant's variables. `applySkin("ha")` and
76
76
  `startHaBridge()` (from `@sukramj/fabric-ui/theme`) do both inside an
77
- Ingress frame and are inert elsewhere.
77
+ Ingress frame and are inert elsewhere. A host on a skin of its own (any
78
+ other `data-skin`, or none) keeps the standalone tokens; the HA skin's
79
+ extras (`accent-color` and `color-scheme` on native controls,
80
+ `--ha-on-primary-color` from Home Assistant's `--text-primary-color`) apply
81
+ only under `data-skin="ha"`. The standalone shell sets the HA skin and the
82
+ mode in a pre-paint script (`src/shell/index.html`) so the first frame
83
+ already wears them; a host that wants the same does it in its own
84
+ `index.html`.
78
85
 
79
86
  ### Event stream
80
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sukramj/fabric-ui",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "The web interface of go-fabric nodes: Svelte 5 pages, UI kit, design tokens with a Home Assistant theme bridge, and the generated API client.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "SukramJ",
@@ -65,7 +65,7 @@
65
65
  "svelte": "^5.57.0"
66
66
  },
67
67
  "dependencies": {
68
- "@lucide/svelte": "1.57.0",
68
+ "@lucide/svelte": "1.59.0",
69
69
  "clsx": "2.1.1",
70
70
  "qrcode": "1.5.4",
71
71
  "tailwind-merge": "3.7.0"
@@ -82,11 +82,11 @@
82
82
  "js-yaml": "4.3.2",
83
83
  "openapi-typescript": "7.13.0",
84
84
  "svelte": "5.57.2",
85
- "svelte-check": "4.7.6",
85
+ "svelte-check": "4.7.7",
86
86
  "tailwindcss": "4.3.3",
87
87
  "typescript": "6.0.3",
88
88
  "vite": "8.3.4",
89
- "vitest": "5.0.4"
89
+ "vitest": "5.0.5"
90
90
  },
91
91
  "engines": {
92
92
  "node": ">=22"
@@ -1,5 +1,6 @@
1
1
  <!-- Ported from openccu-loom assets/ui/src/lib/components/ui//Button.svelte:1-72 at b40b289a; the disabled fills use the
2
- tokens instead of the slate ramp. -->
2
+ tokens instead of the slate ramp, and the label on the primary fill uses --ha-on-primary-color (Home Assistant's
3
+ --text-primary-color under the HA skin). -->
3
4
  <script lang="ts">
4
5
  import type { Snippet } from "svelte";
5
6
  import type { HTMLButtonAttributes } from "svelte/elements";
@@ -18,7 +19,7 @@
18
19
  "disabled:bg-[var(--ha-secondary-background-color)] disabled:text-[var(--ha-disabled-text-color)] disabled:shadow-none";
19
20
  const disabledMuted = "disabled:opacity-50 disabled:text-[var(--ha-disabled-text-color)]";
20
21
  const variants: Record<Variant, string> = {
21
- default: `bg-[var(--ha-primary-color)] text-white hover:bg-[var(--ha-primary-color-hover)] shadow-sm ${disabledFill}`,
22
+ default: `bg-[var(--ha-primary-color)] text-[var(--ha-on-primary-color)] hover:bg-[var(--ha-primary-color-hover)] shadow-sm ${disabledFill}`,
22
23
  outline: `border border-[var(--ha-divider-color)] bg-[var(--ha-card-background-color)] text-[var(--ha-primary-text-color)] hover:bg-[var(--ha-secondary-background-color)] ${disabledMuted}`,
23
24
  ghost: `text-[var(--ha-primary-text-color)] hover:bg-[var(--ha-secondary-background-color)] ${disabledMuted}`,
24
25
  destructive: `bg-[var(--ha-error-color)] text-white hover:brightness-95 shadow-sm ${disabledFill}`,
@@ -20,14 +20,17 @@
20
20
 
21
21
  const listClass = $derived(
22
22
  variant === "underline"
23
- ? cn("flex gap-1 overflow-x-auto border-b border-[var(--ha-divider-color)]", cls)
23
+ ? // The divider is an inset shadow, not a border the active marker
24
+ // overlaps with -mb-px: that 1px overflow made the scrollable list
25
+ // show a vertical scrollbar.
26
+ cn("flex gap-1 overflow-x-auto overflow-y-hidden shadow-[inset_0_-1px_0_var(--ha-divider-color)]", cls)
24
27
  : cn("inline-flex flex-wrap gap-0.5 rounded-lg bg-[var(--ha-secondary-background-color)] p-0.5", cls),
25
28
  );
26
29
 
27
30
  function itemClass(isActive: boolean): string {
28
31
  if (variant === "underline") {
29
32
  return cn(
30
- "-mb-px inline-flex items-center justify-center gap-2 whitespace-nowrap border-b-2 px-4 py-3 text-center text-sm font-medium transition",
33
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap border-b-2 px-4 py-3 text-center text-sm font-medium transition",
31
34
  fill && "flex-1",
32
35
  isActive
33
36
  ? "border-[var(--ha-primary-color)] text-[var(--ha-primary-color)]"
@@ -115,7 +115,10 @@ export function startHaBridge(): () => void {
115
115
  const ps = parentWin.getComputedStyle(parentRoot);
116
116
  for (const name of HA_THEME_VARS) {
117
117
  const value = ps.getPropertyValue(name).trim();
118
+ // A variable the parent no longer defines (a theme switched back
119
+ // to the default) is dropped, so the token falls back again.
118
120
  if (value) ourRoot.style.setProperty(name, value);
121
+ else ourRoot.style.removeProperty(name);
119
122
  }
120
123
  // Follow Home Assistant's light/dark by its background luminance;
121
124
  // this overrides the page's own choice while embedded.
@@ -7,7 +7,9 @@
7
7
  * on <html> flips it).
8
8
  * - html[data-skin="ha"] — the tokens resolve from Home Assistant's own
9
9
  * variables (var(--primary-color, …)); ha-bridge.ts copies the live values
10
- * onto :root inside an Ingress frame, and the literals are the defaults.
10
+ * onto :root inside an Ingress frame, and the literals are the defaults:
11
+ * Home Assistant's own default light and dark palettes. The standalone
12
+ * shell uses this skin too, set before the first paint (index.html).
11
13
  * - the palette remap recolours plain Tailwind palette utilities under the
12
14
  * HA skin.
13
15
  * - .table-reflow turns a data table into cards on a phone.
@@ -45,6 +47,8 @@
45
47
  --ha-elevation-modal: 0 10px 25px -5px rgb(0 0 0 / 0.15);
46
48
  --ha-radius-card: 12px;
47
49
  --ha-radius-control: 8px;
50
+ /* The label on a primary fill. */
51
+ --ha-on-primary-color: #ffffff;
48
52
  }
49
53
 
50
54
  html.dark {
@@ -92,6 +96,11 @@ html[data-skin="ha"] {
92
96
  --ha-elevation-card: var(--ha-card-box-shadow, none); /* HA cards are flat */
93
97
  --ha-elevation-modal: var(--ha-card-box-shadow, 0 8px 24px rgba(0, 0, 0, 0.18));
94
98
  --font-sans: var(--ha-font-family-body, "Roboto", "Noto", "Helvetica Neue", Arial, sans-serif);
99
+ /* Home Assistant's text-on-primary, for a light primary in a custom theme. */
100
+ --ha-on-primary-color: var(--text-primary-color, #ffffff);
101
+ /* Native controls (checkboxes, radios, range, scrollbars) take the theme. */
102
+ accent-color: var(--ha-primary-color);
103
+ color-scheme: light;
95
104
  }
96
105
 
97
106
  html[data-skin="ha"].dark {
@@ -105,6 +114,7 @@ html[data-skin="ha"].dark {
105
114
  --ha-primary-text-color: var(--primary-text-color, #e1e1e1);
106
115
  --ha-secondary-text-color: var(--secondary-text-color, #9b9b9b);
107
116
  --ha-disabled-text-color: var(--disabled-text-color, #6f6f6f);
117
+ color-scheme: dark;
108
118
  }
109
119
 
110
120
  /* Base document colours track the theme tokens so the boot paint and any