@the-portland-company/shell 0.47.0 → 0.47.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,35 @@
1
+ ## 0.47.1 — 2026-08-13
2
+
3
+ Two fixes found by running a consuming app's WCAG contrast gate against 0.47.0.
4
+ Both are 0.47.0 defects; nothing from before 0.47.0 is affected.
5
+
6
+ ### Fixed — `--color-danger` collided with apps' own Tailwind theme colour
7
+
8
+ 0.47.0 introduced `--color-danger` at `:root` to separate "attention/error" from
9
+ "accent". The name was a bad choice: Tailwind v4 derives utilities from
10
+ `--color-*` theme keys, and Petitions already defined
11
+ `--color-danger: var(--tone-danger)` (`#c53030`) to back its `bg-danger` badges.
12
+ The shell's declaration won the cascade, so every `bg-danger` element repainted
13
+ from `#c53030` to `#E63946` — dropping white-on-danger from 6.2:1 to **4.17:1**
14
+ and failing WCAG AA on eight badges in one view.
15
+
16
+ Renamed to **`--chrome-danger`**. The shell should not squat a generic
17
+ `--color-*` name that apps legitimately own; `--color-accent` stays as it is,
18
+ because that one is a documented chrome alias apps already consume.
19
+
20
+ ### Fixed — a Mode accent must not carry into dark
21
+
22
+ 0.47.0 let a Mode's accent through to dark on the theory that a foreground
23
+ colour is safe there. Measured: Petition Mode's `#15803D` on the dark elevated
24
+ panel `#1F1F1F` is **3.29:1**, and it regressed fourteen routes at once.
25
+
26
+ A Mode's palette is authored against white. Nothing makes it legible against
27
+ black, and deriving a dark variant would be inventing a dark theme for a Mode
28
+ whose design never had one — which the brief explicitly ruled out. So a Mode
29
+ accent is now reset under `.dark`, and dark keeps the platform's neutral ramp
30
+ exactly as it did on 0.46.0. This is chrome POLICY, in `chrome.css`, so no Mode
31
+ can opt out of it by authoring a value.
32
+
1
33
  ## 0.47.0 — 2026-08-13
2
34
 
3
35
  Petition Mode has been green since V1 and has rendered red for the whole of the
@@ -20,7 +52,7 @@ Besides mis-signalling, it made the accent unoverridable — apps reasonably set
20
52
 
21
53
  Those 32 references now resolve a semantic token, split by what the colour
22
54
  actually means: `--color-accent` for genuine accent furniture, and a new
23
- `--color-danger` for attention and error (count badges, the low-fuel meter and
55
+ `--chrome-danger` for attention and error (count badges, the low-fuel meter and
24
56
  its nudge, validation messages). The danger set stays red in every Mode — a
25
57
  green "3 unread" badge is worse than a red one.
26
58
 
@@ -165,7 +165,7 @@ function resolveOrgLogoUrl(url) {
165
165
  return `${CORE_APP_ORIGIN}${raw.startsWith("/") ? "" : "/"}${raw}`;
166
166
  }
167
167
  function topBarIconButtonClass(tone = "default") {
168
- const toneClass = tone === "danger" || tone === "warning" ? "text-[color:var(--color-danger)] hover:text-[color:var(--color-danger)]" : "text-[color:var(--topbar-icon-color,var(--muted))] hover:text-[color:var(--topbar-icon-hover-color,var(--foreground))] hover:bg-[color:var(--topbar-icon-hover-bg,transparent)]";
168
+ const toneClass = tone === "danger" || tone === "warning" ? "text-[color:var(--chrome-danger)] hover:text-[color:var(--chrome-danger)]" : "text-[color:var(--topbar-icon-color,var(--muted))] hover:text-[color:var(--topbar-icon-hover-color,var(--foreground))] hover:bg-[color:var(--topbar-icon-hover-bg,transparent)]";
169
169
  return [
170
170
  // `group/tbtip` powers the shared <TopBarTooltip> rendered inside the trigger.
171
171
  "group/tbtip relative flex items-center justify-center rounded-full border border-[color:var(--line)] transition",
@@ -192,7 +192,7 @@ function useAnyTopBarPanelOpen() {
192
192
  }
193
193
  function TopBarCountBadge({ count }) {
194
194
  if (!(count > 0)) return null;
195
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--color-danger)] px-1 text-[10px] font-normal leading-none text-white", children: count > 99 ? "99+" : count });
195
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--chrome-danger)] px-1 text-[10px] font-normal leading-none text-white", children: count > 99 ? "99+" : count });
196
196
  }
197
197
  function TopBarTooltip({
198
198
  title,
@@ -516,7 +516,7 @@ function FuelRow({
516
516
  {
517
517
  className: [
518
518
  "text-xs font-semibold tabular-nums",
519
- low ? "text-[color:var(--color-danger)]" : "text-[color:var(--muted)]"
519
+ low ? "text-[color:var(--chrome-danger)]" : "text-[color:var(--muted)]"
520
520
  ].join(" "),
521
521
  children: [
522
522
  remaining.toLocaleString(),
@@ -540,7 +540,7 @@ function FuelRow({
540
540
  {
541
541
  className: [
542
542
  "h-full rounded-full transition-[width]",
543
- low ? "bg-[color:var(--color-danger)]" : "bg-[color:var(--color-ok,#00A651)]"
543
+ low ? "bg-[color:var(--chrome-danger)]" : "bg-[color:var(--color-ok,#00A651)]"
544
544
  ].join(" "),
545
545
  style: { width: `${ratio}%` }
546
546
  }
@@ -576,14 +576,14 @@ function LowFuelHint({ lowFuel, orgId }) {
576
576
  "div",
577
577
  {
578
578
  role: "status",
579
- className: "absolute right-0 top-[calc(100%+10px)] z-50 w-60 rounded-lg border border-[color:var(--color-danger)] bg-[color:var(--color-danger)] px-3 py-2 text-white shadow-[var(--shadow-soft)]",
579
+ className: "absolute right-0 top-[calc(100%+10px)] z-50 w-60 rounded-lg border border-[color:var(--chrome-danger)] bg-[color:var(--chrome-danger)] px-3 py-2 text-white shadow-[var(--shadow-soft)]",
580
580
  onClick: (e) => e.stopPropagation(),
581
581
  children: [
582
582
  /* @__PURE__ */ jsxRuntime.jsx(
583
583
  "span",
584
584
  {
585
585
  "aria-hidden": true,
586
- className: "absolute -top-[5px] right-[11px] h-2.5 w-2.5 rotate-45 bg-[color:var(--color-danger)]"
586
+ className: "absolute -top-[5px] right-[11px] h-2.5 w-2.5 rotate-45 bg-[color:var(--chrome-danger)]"
587
587
  }
588
588
  ),
589
589
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
@@ -1237,7 +1237,7 @@ function SupportAction({ orgId } = {}) {
1237
1237
  className: "w-full rounded-lg border border-[color:var(--line)] bg-[color:var(--panel)] px-3 py-2 text-sm text-[color:var(--foreground)] placeholder:text-[color:var(--muted)] focus:outline-none focus:ring-2 focus:ring-[color:var(--color-accent)]"
1238
1238
  }
1239
1239
  ),
1240
- showEmailError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 block text-xs text-[color:var(--color-danger)]", children: "Enter an email so support can reply." }) : null
1240
+ showEmailError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 block text-xs text-[color:var(--chrome-danger)]", children: "Enter an email so support can reply." }) : null
1241
1241
  ] }) : null,
1242
1242
  missingPhone ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "mt-3 block", children: [
1243
1243
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block text-xs font-semibold text-[color:var(--foreground)]", children: "Your phone \u2014 optional" }),
@@ -1262,7 +1262,7 @@ function SupportAction({ orgId } = {}) {
1262
1262
  className: "mt-4 w-full resize-y rounded-lg border border-[color:var(--line)] bg-[color:var(--panel)] px-3 py-2 text-sm text-[color:var(--foreground)] placeholder:text-[color:var(--muted)] focus:outline-none focus:ring-2 focus:ring-[color:var(--color-accent)]"
1263
1263
  }
1264
1264
  ),
1265
- state === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-[color:var(--color-danger)]", children: "Sending failed \u2014 try again." }) : null,
1265
+ state === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-[color:var(--chrome-danger)]", children: "Sending failed \u2014 try again." }) : null,
1266
1266
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [
1267
1267
  /* @__PURE__ */ jsxRuntime.jsx(
1268
1268
  "button",