@the-portland-company/shell 0.47.0 → 0.48.0-rc.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 +69 -1
- package/dist/app-chrome.cjs +57 -24
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +21 -3
- package/dist/app-chrome.d.ts +21 -3
- package/dist/app-chrome.js +14 -6
- package/dist/app-chrome.js.map +1 -1
- package/dist/chrome.css +38 -3
- package/dist/{chunk-E6LI44BT.js → chunk-DYD2J5CC.js} +46 -21
- package/dist/chunk-DYD2J5CC.js.map +1 -0
- package/dist/native.cjs +44 -19
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +10 -0
- package/dist/native.d.ts +10 -0
- 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,71 @@
|
|
|
1
|
+
## 0.48.0 — 2026-08-13
|
|
2
|
+
|
|
3
|
+
V1-parity round 2, driven by a measured element-by-element audit of a live V1
|
|
4
|
+
build against 0.47.1. Two kinds of change: one global conformance fix, and a
|
|
5
|
+
set of registry/Mode opt-ins that are byte-identical for apps that declare
|
|
6
|
+
nothing.
|
|
7
|
+
|
|
8
|
+
### Fixed — the sidebar now consumes its own Brand tokens (GLOBAL)
|
|
9
|
+
|
|
10
|
+
"Sidebar width, colors, item radius, and spacing come from `--sidebar-*`"
|
|
11
|
+
(Reference/UI-Platform) — but the chrome painted the bar from `--surface-1`
|
|
12
|
+
and rows from `--muted`, so `--sidebar-bg: #FFFFFF` and
|
|
13
|
+
`--sidebar-text: #2F3136` were dead tokens and a Brand edit to them did
|
|
14
|
+
nothing. Consuming them changes every app toward what the Brand editor
|
|
15
|
+
declares: white rail, dark rows in light; the same #161616 ramp in dark
|
|
16
|
+
(dark values added to chrome.css's own `.dark` block so stylesheet order
|
|
17
|
+
between chrome.css and the runtime sheet cannot flip them). This also ends
|
|
18
|
+
the app-wide 3.65:1 AA failure on every inactive row (now 12.6:1).
|
|
19
|
+
|
|
20
|
+
### Added — opt-in, byte-identical defaults
|
|
21
|
+
|
|
22
|
+
- **Org pill takes the Mode accent** (`--mode-accent` / `--mode-on-accent`,
|
|
23
|
+
the latter luminance-derived by the Brand API). Neutral everywhere a Mode
|
|
24
|
+
declares nothing, and in dark.
|
|
25
|
+
- **`navShape: 'flat'` (registry)** — a rail whose whole tree nests under one
|
|
26
|
+
entry renders the children at the root: no parent "Dashboard" row, no
|
|
27
|
+
accordion; rows take the wash active treatment (V1's rail rows).
|
|
28
|
+
- **`beta: false` (registry)** — omits the Beta banner strip for that app.
|
|
29
|
+
- **`'title'` grant** — a granted app's pages may publish the top-bar title
|
|
30
|
+
("Batches", not the app name on every page).
|
|
31
|
+
- **Granted breadcrumbs now REPLACE the derived trail** (like core): a page
|
|
32
|
+
that publishes none shows none, instead of inheriting
|
|
33
|
+
"Dashboard › <page>" from a tree it opted out of.
|
|
34
|
+
|
|
35
|
+
Petitions is the only registry row using any of these.
|
|
36
|
+
|
|
37
|
+
## 0.47.1 — 2026-08-13
|
|
38
|
+
|
|
39
|
+
Two fixes found by running a consuming app's WCAG contrast gate against 0.47.0.
|
|
40
|
+
Both are 0.47.0 defects; nothing from before 0.47.0 is affected.
|
|
41
|
+
|
|
42
|
+
### Fixed — `--color-danger` collided with apps' own Tailwind theme colour
|
|
43
|
+
|
|
44
|
+
0.47.0 introduced `--color-danger` at `:root` to separate "attention/error" from
|
|
45
|
+
"accent". The name was a bad choice: Tailwind v4 derives utilities from
|
|
46
|
+
`--color-*` theme keys, and Petitions already defined
|
|
47
|
+
`--color-danger: var(--tone-danger)` (`#c53030`) to back its `bg-danger` badges.
|
|
48
|
+
The shell's declaration won the cascade, so every `bg-danger` element repainted
|
|
49
|
+
from `#c53030` to `#E63946` — dropping white-on-danger from 6.2:1 to **4.17:1**
|
|
50
|
+
and failing WCAG AA on eight badges in one view.
|
|
51
|
+
|
|
52
|
+
Renamed to **`--chrome-danger`**. The shell should not squat a generic
|
|
53
|
+
`--color-*` name that apps legitimately own; `--color-accent` stays as it is,
|
|
54
|
+
because that one is a documented chrome alias apps already consume.
|
|
55
|
+
|
|
56
|
+
### Fixed — a Mode accent must not carry into dark
|
|
57
|
+
|
|
58
|
+
0.47.0 let a Mode's accent through to dark on the theory that a foreground
|
|
59
|
+
colour is safe there. Measured: Petition Mode's `#15803D` on the dark elevated
|
|
60
|
+
panel `#1F1F1F` is **3.29:1**, and it regressed fourteen routes at once.
|
|
61
|
+
|
|
62
|
+
A Mode's palette is authored against white. Nothing makes it legible against
|
|
63
|
+
black, and deriving a dark variant would be inventing a dark theme for a Mode
|
|
64
|
+
whose design never had one — which the brief explicitly ruled out. So a Mode
|
|
65
|
+
accent is now reset under `.dark`, and dark keeps the platform's neutral ramp
|
|
66
|
+
exactly as it did on 0.46.0. This is chrome POLICY, in `chrome.css`, so no Mode
|
|
67
|
+
can opt out of it by authoring a value.
|
|
68
|
+
|
|
1
69
|
## 0.47.0 — 2026-08-13
|
|
2
70
|
|
|
3
71
|
Petition Mode has been green since V1 and has rendered red for the whole of the
|
|
@@ -20,7 +88,7 @@ Besides mis-signalling, it made the accent unoverridable — apps reasonably set
|
|
|
20
88
|
|
|
21
89
|
Those 32 references now resolve a semantic token, split by what the colour
|
|
22
90
|
actually means: `--color-accent` for genuine accent furniture, and a new
|
|
23
|
-
`--
|
|
91
|
+
`--chrome-danger` for attention and error (count badges, the low-fuel meter and
|
|
24
92
|
its nudge, validation messages). The danger set stays red in every Mode — a
|
|
25
93
|
green "3 unread" badge is worse than a red one.
|
|
26
94
|
|
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",
|
|
@@ -1766,7 +1766,7 @@ function NavSidebar({
|
|
|
1766
1766
|
setOpenGroup(activeGroupKey);
|
|
1767
1767
|
}, [activeGroupKey]);
|
|
1768
1768
|
const toggleGroup = (key) => setOpenGroup((prev) => prev === key ? null : key);
|
|
1769
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "fixed inset-y-0 left-0 z-30 hidden w-[240px] flex-col border-r border-[color:var(--line)] bg-[color:var(--nav-surface)] lg:flex", children: [
|
|
1769
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "fixed inset-y-0 left-0 z-30 hidden w-[240px] flex-col border-r border-[color:var(--line)] bg-[color:var(--sidebar-bg,var(--nav-surface))] lg:flex", children: [
|
|
1770
1770
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1771
1771
|
Link,
|
|
1772
1772
|
{
|
|
@@ -1792,7 +1792,7 @@ function NavSidebar({
|
|
|
1792
1792
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-y-auto px-4 pb-2", children: [
|
|
1793
1793
|
org ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3", children: [
|
|
1794
1794
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between px-1", children: [
|
|
1795
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Organization" }),
|
|
1795
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: "Organization" }),
|
|
1796
1796
|
org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
|
|
1797
1797
|
] }),
|
|
1798
1798
|
org.loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2.5 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 shadow-sm", children: [
|
|
@@ -1812,7 +1812,7 @@ function NavSidebar({
|
|
|
1812
1812
|
),
|
|
1813
1813
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading organization" })
|
|
1814
1814
|
] }) : org.organizations && org.organizations.length > 0 && org.onSwitch ? /* @__PURE__ */ jsxRuntime.jsxs("details", { "data-nav-details": true, className: "group relative", children: [
|
|
1815
|
-
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex w-full cursor-pointer list-none items-center justify-between gap-2 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)] [&::-webkit-details-marker]:hidden", children: [
|
|
1815
|
+
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex w-full cursor-pointer list-none items-center justify-between gap-2 rounded-md border border-[color:var(--mode-accent,var(--line))] bg-[color:var(--mode-accent,var(--panel-elevated))] px-2.5 py-2 text-left text-[color:var(--mode-on-accent,var(--foreground))] shadow-sm transition hover:bg-[color:var(--mode-accent-strong,var(--panel))] [&::-webkit-details-marker]:hidden", children: [
|
|
1816
1816
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
1817
1817
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1818
1818
|
"span",
|
|
@@ -1875,7 +1875,7 @@ function NavSidebar({
|
|
|
1875
1875
|
{
|
|
1876
1876
|
type: "button",
|
|
1877
1877
|
onClick: org.onClick,
|
|
1878
|
-
className: "flex w-full items-center justify-between gap-2 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)]",
|
|
1878
|
+
className: "flex w-full items-center justify-between gap-2 rounded-md border border-[color:var(--mode-accent,var(--line))] bg-[color:var(--mode-accent,var(--panel-elevated))] px-2.5 py-2 text-left text-[color:var(--mode-on-accent,var(--foreground))] shadow-sm transition hover:bg-[color:var(--mode-accent-strong,var(--panel))]",
|
|
1879
1879
|
children: [
|
|
1880
1880
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
1881
1881
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1940,7 +1940,7 @@ function NavSidebar({
|
|
|
1940
1940
|
}
|
|
1941
1941
|
) }) : null,
|
|
1942
1942
|
/* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex flex-col gap-1", children: [
|
|
1943
|
-
nav.groupLabel ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 pb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: nav.groupLabel }) : null,
|
|
1943
|
+
nav.groupLabel ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 pb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: nav.groupLabel }) : null,
|
|
1944
1944
|
nav.items.map((item, idx) => {
|
|
1945
1945
|
if (item.kind === "section") {
|
|
1946
1946
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1952,6 +1952,30 @@ function NavSidebar({
|
|
|
1952
1952
|
`section-${idx}-${item.label}`
|
|
1953
1953
|
);
|
|
1954
1954
|
}
|
|
1955
|
+
if (nav.flatten && item.children && item.children.length > 0) {
|
|
1956
|
+
return item.children.map((child, i) => {
|
|
1957
|
+
if (child.kind === "section") {
|
|
1958
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1959
|
+
NavSectionRow,
|
|
1960
|
+
{
|
|
1961
|
+
label: child.label,
|
|
1962
|
+
first: idx === 0 && i === 0
|
|
1963
|
+
},
|
|
1964
|
+
`flat-section-${idx}-${i}-${child.label}`
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1968
|
+
NavRow,
|
|
1969
|
+
{
|
|
1970
|
+
item: child,
|
|
1971
|
+
active: child.href ? activeFn(pathname, child.href) : false,
|
|
1972
|
+
Link,
|
|
1973
|
+
variant: "flat"
|
|
1974
|
+
},
|
|
1975
|
+
child.href ?? `flat-${idx}-${i}-${child.label}`
|
|
1976
|
+
);
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1955
1979
|
if (item.children && item.children.length > 0) {
|
|
1956
1980
|
const key = groupKeyOf(item, idx);
|
|
1957
1981
|
const selfActive = item.href ? activeFn(pathname, item.href) : false;
|
|
@@ -2059,7 +2083,7 @@ function NavSectionRow({
|
|
|
2059
2083
|
"p",
|
|
2060
2084
|
{
|
|
2061
2085
|
className: [
|
|
2062
|
-
"text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]",
|
|
2086
|
+
"text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]",
|
|
2063
2087
|
variant === "sub" ? "px-3 pb-0.5" : "px-2 pb-1",
|
|
2064
2088
|
first ? "" : "mt-3"
|
|
2065
2089
|
].join(" "),
|
|
@@ -2075,14 +2099,15 @@ function NavRow({
|
|
|
2075
2099
|
}) {
|
|
2076
2100
|
const Icon = item.icon;
|
|
2077
2101
|
const isSub = variant === "sub";
|
|
2078
|
-
const
|
|
2102
|
+
const washActive = variant !== "top";
|
|
2103
|
+
const activeClasses = washActive ? "bg-[color:var(--mode-accent-surface,var(--panel-elevated))] text-[color:var(--color-accent)] shadow-sm" : "bg-[color:var(--color-accent)] text-white shadow-sm";
|
|
2079
2104
|
const wrapperClasses = [
|
|
2080
2105
|
"group relative block overflow-hidden rounded-md transition",
|
|
2081
|
-
active ? activeClasses : "text-[color:var(--muted)] hover:text-white"
|
|
2106
|
+
active ? activeClasses : "text-[color:var(--sidebar-text,var(--muted))] hover:text-white"
|
|
2082
2107
|
].join(" ");
|
|
2083
2108
|
const rowPadding = isSub ? "px-3 py-1.5 text-[13px]" : "px-3 py-2 text-sm";
|
|
2084
2109
|
const iconSize = isSub ? 16 : 18;
|
|
2085
|
-
const iconClass = active && !
|
|
2110
|
+
const iconClass = active && !washActive ? "text-white" : "text-current";
|
|
2086
2111
|
const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2087
2112
|
!active ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2088
2113
|
"span",
|
|
@@ -2147,7 +2172,7 @@ function NavGroup({
|
|
|
2147
2172
|
const headerClasses = [
|
|
2148
2173
|
"group relative block w-full overflow-hidden text-left transition",
|
|
2149
2174
|
open ? "rounded-t-md" : "rounded-md",
|
|
2150
|
-
active ? "bg-[color:var(--color-accent)] text-white shadow-sm" : open ? "bg-[color:var(--panel)] text-[color:var(--foreground)]" : "text-[color:var(--muted)] hover:text-white"
|
|
2175
|
+
active ? "bg-[color:var(--color-accent)] text-white shadow-sm" : open ? "bg-[color:var(--panel)] text-[color:var(--foreground)]" : "text-[color:var(--sidebar-text,var(--muted))] hover:text-white"
|
|
2151
2176
|
].join(" ");
|
|
2152
2177
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2153
2178
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2244,7 +2269,7 @@ function NavSubGroup({
|
|
|
2244
2269
|
"aria-expanded": open,
|
|
2245
2270
|
className: [
|
|
2246
2271
|
"flex w-full items-center gap-2.5 rounded px-3 py-1.5 text-left text-[13px] font-medium transition",
|
|
2247
|
-
ownsActive ? "text-[color:var(--color-accent)]" : "text-[color:var(--muted)] hover:bg-[color:var(--nav-row-hover)] hover:text-[color:var(--foreground)]"
|
|
2272
|
+
ownsActive ? "text-[color:var(--color-accent)]" : "text-[color:var(--sidebar-text,var(--muted))] hover:bg-[color:var(--nav-row-hover)] hover:text-[color:var(--foreground)]"
|
|
2248
2273
|
].join(" "),
|
|
2249
2274
|
children: [
|
|
2250
2275
|
Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: 15, className: "shrink-0 text-current" }) : null,
|
|
@@ -3037,7 +3062,11 @@ var POLITOGY_APPS = {
|
|
|
3037
3062
|
// <main>), and its adjudication case is addressed per sheet and per line —
|
|
3038
3063
|
// a trail derived from the nav tree reads "Dashboard › Adjudication" on
|
|
3039
3064
|
// every one of those URLs and cannot name the record you are actually on.
|
|
3040
|
-
|
|
3065
|
+
// 'title' for the same reason: its pages have real names ("Batches"),
|
|
3066
|
+
// where the registry can only say "Petitions".
|
|
3067
|
+
grants: ["contentWrapper", "breadcrumbs", "title"],
|
|
3068
|
+
navShape: "flat",
|
|
3069
|
+
beta: false
|
|
3041
3070
|
},
|
|
3042
3071
|
// Campaign Mode apps — each scoped to Campaign, so they render the Campaign
|
|
3043
3072
|
// tree and a static Campaign pill. Not yet deployed; hidden from the Campaign
|
|
@@ -3178,7 +3207,7 @@ function FrameBody({
|
|
|
3178
3207
|
() => deriveBreadcrumbs(navItems, pathname, { search, origin: meta.origin }),
|
|
3179
3208
|
[navItems, pathname, search, meta.origin]
|
|
3180
3209
|
);
|
|
3181
|
-
const breadcrumbs = core ? core.page?.breadcrumbs : granted("breadcrumbs")
|
|
3210
|
+
const breadcrumbs = core ? core.page?.breadcrumbs : grants?.includes("breadcrumbs") ? granted("breadcrumbs") : derivedBreadcrumbs;
|
|
3182
3211
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3183
3212
|
NavAppShell,
|
|
3184
3213
|
{
|
|
@@ -3191,7 +3220,11 @@ function FrameBody({
|
|
|
3191
3220
|
title: "Politogy"
|
|
3192
3221
|
},
|
|
3193
3222
|
nav: {
|
|
3194
|
-
|
|
3223
|
+
// A flat rail's sub-menu IS the nav, so the 'tabs only' preference
|
|
3224
|
+
// (which strips children) would leave one childless parent row —
|
|
3225
|
+
// flat apps ignore the stripping.
|
|
3226
|
+
items: navDisplay === "tabs" && meta.navShape !== "flat" ? navItems.map(({ children: _sub, ...item }) => item) : navItems,
|
|
3227
|
+
flatten: meta.navShape === "flat"
|
|
3195
3228
|
},
|
|
3196
3229
|
// The app's own workspace is NOT the organization — it is a per-app
|
|
3197
3230
|
// bootstrap account with a different id in every app. Showing it while
|
|
@@ -3210,13 +3243,13 @@ function FrameBody({
|
|
|
3210
3243
|
footer,
|
|
3211
3244
|
linkComponent
|
|
3212
3245
|
},
|
|
3213
|
-
betaBanner: {},
|
|
3246
|
+
betaBanner: meta.beta === false ? void 0 : {},
|
|
3214
3247
|
modeId: appMode,
|
|
3215
3248
|
contentWrapper: core?.contentWrapper ?? granted("contentWrapper"),
|
|
3216
3249
|
topBar: {
|
|
3217
3250
|
// Core's pages publish their own identity; every other app is one
|
|
3218
3251
|
// product surface and takes its registry title.
|
|
3219
|
-
title: core?.page?.title ?? meta.title,
|
|
3252
|
+
title: core?.page?.title ?? (grants?.includes("title") ? data?.frame?.title : void 0) ?? meta.title,
|
|
3220
3253
|
breadcrumbs,
|
|
3221
3254
|
user: {
|
|
3222
3255
|
name: identity.userName,
|