@the-portland-company/shell 0.47.0-rc.3 → 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 +65 -4
- package/dist/app-chrome.cjs +8 -8
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.js +1 -1
- package/dist/chrome.css +30 -3
- package/dist/{chunk-E6LI44BT.js → chunk-PS6IIPPE.js} +10 -10
- package/dist/chunk-PS6IIPPE.js.map +1 -0
- package/dist/native.cjs +8 -8
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-E6LI44BT.js.map +0 -1
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
|
-
`--
|
|
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
|
|
|
@@ -64,9 +96,25 @@ Dark mode keeps the platform's neutral ramp. The Brand sheet resets the Mode
|
|
|
64
96
|
SURFACES to the guaranteed-invalid value under `.dark` so they fall through to
|
|
65
97
|
the neutrals; only the accent, a foreground colour, carries over.
|
|
66
98
|
|
|
67
|
-
Active sub-rows also gain a 3px left rail drawn from
|
|
68
|
-
|
|
69
|
-
|
|
99
|
+
Active sub-rows also gain a 3px left rail drawn from
|
|
100
|
+
`var(--mode-accent, transparent)` — invisible and out of flow for any app whose
|
|
101
|
+
Mode declares no chrome group.
|
|
102
|
+
|
|
103
|
+
**Where Mode SURFACES are read matters, and the rule is not obvious.** They are
|
|
104
|
+
resolved at the point of use with the pre-0.47 value as an inline fallback:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
bg-[color:var(--mode-accent-surface,var(--panel-elevated))]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Not through an alias declared in the `[data-politogy-mode]` block — that block
|
|
111
|
+
does not match an app which is not mode-scoped, so the alias would be unset and
|
|
112
|
+
a bare `var()` is invalid at computed-value time, dropping the property to its
|
|
113
|
+
initial value. And not through a `:root` alias either — `.dark` is a separate
|
|
114
|
+
top-level selector, so a `:root` alias substitutes the LIGHT value and inherits
|
|
115
|
+
it into dark. Point of use is the only placement correct in both themes, scoped
|
|
116
|
+
and unscoped. Two tests enforce it; both mistakes were made and caught during
|
|
117
|
+
the release candidates.
|
|
70
118
|
|
|
71
119
|
Needs the matching Brand API release (`tokens.modes.<id>.chrome`).
|
|
72
120
|
|
|
@@ -108,6 +156,19 @@ a silent effect.
|
|
|
108
156
|
|
|
109
157
|
A grant is for a fact only the app HAS, never for a look.
|
|
110
158
|
|
|
159
|
+
### Added — the brand lockup follows the Mode
|
|
160
|
+
|
|
161
|
+
`brandLogoSrc` became core-only in 0.43, so every mode-scoped app rendered the
|
|
162
|
+
Relationship lockup — a red wordmark on a purple `vrm` badge — whatever Mode it
|
|
163
|
+
was scoped to. Petition Mode shipped a green Petition lockup in V1 and lost it in
|
|
164
|
+
that migration.
|
|
165
|
+
|
|
166
|
+
Resolved from the registry by Mode, like the accent:
|
|
167
|
+
`MODE_BRAND_LOGOS = { petition: '/brand/logos/petition-mode-logo.svg' }`. Only
|
|
168
|
+
Modes with a shipped lockup are listed; everything else keeps today's default.
|
|
169
|
+
The path is app-relative, so add the asset to the app's `public/` before adding
|
|
170
|
+
a Mode here.
|
|
171
|
+
|
|
111
172
|
### Changed — prereleases publish under the `next` dist-tag
|
|
112
173
|
|
|
113
174
|
`npm publish` tags `latest` whatever the semver, so an rc would silently become
|
package/dist/app-chrome.cjs
CHANGED
|
@@ -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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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",
|