@broberg/app-shell 0.7.1 → 0.8.0
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 +12 -0
- package/css/app-shell.css +3 -1
- package/dist/preact.cjs +16 -3
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +7 -1
- package/dist/preact.d.ts +7 -1
- package/dist/preact.js +17 -4
- package/dist/preact.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,18 @@ the user menu reads and writes theme, palette, surfaces and backdrop through it.
|
|
|
53
53
|
| `TenantSwitcher` | The user's own organisations, the active one marked, switching through the app's route (0.7.1). |
|
|
54
54
|
| `AnalyticsPage` | The app's own visitors, page views, page views per day and most visited pages, from Upmetrics (0.6.0). |
|
|
55
55
|
|
|
56
|
+
## 0.8.0 — TenantSwitcher on a phone (F029.10, found by appkit's pilot)
|
|
57
|
+
|
|
58
|
+
- **The menu stays on screen.** It is anchored to the switcher, which sits among
|
|
59
|
+
your actions rather than at the edge, so at 393 px it ran off the right side.
|
|
60
|
+
It is now measured when it opens and shifted back inside, 16 px from the edge.
|
|
61
|
+
- **Changed output: no raw role.** Roles are your app's words, so the switcher
|
|
62
|
+
cannot translate them, and a bare «member» in a Danish UI is worse than nothing.
|
|
63
|
+
Pass `roleLabel={(role) => …}` to show them; without it, other rows show no role.
|
|
64
|
+
The active row still says «aktiv», and a suspended one still says so.
|
|
65
|
+
- **On a phone the switcher takes at most 40% of the width**, and the organisation
|
|
66
|
+
name is cut with «…» before the page title is.
|
|
67
|
+
|
|
56
68
|
## 0.7.1 — TenantSwitcher: the user's own organisations (F029.10)
|
|
57
69
|
|
|
58
70
|
0.7.0 was tagged but never reached npm: the secret gate stopped it on a test fixture key, now listed in `.gitleaksignore`.
|
package/css/app-shell.css
CHANGED
|
@@ -382,7 +382,9 @@
|
|
|
382
382
|
.bas-tenant__btn:hover, .bas-tenant__btn.is-open { background: var(--active); }
|
|
383
383
|
.bas-tenant__btn::after { content: "▾"; font-size: 10px; color: var(--fg-muted); flex: none; }
|
|
384
384
|
.bas-tenant__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 500; }
|
|
385
|
-
.bas-tenant__menu { left: 0; right: auto; }
|
|
385
|
+
.bas-tenant__menu { left: 0; right: auto; max-width: calc(100vw - 32px); }
|
|
386
|
+
/* phone: the org name gives way before the page title does */
|
|
387
|
+
@media (max-width: 767px) { .bas-tenant { max-width: 40vw; } }
|
|
386
388
|
.bas-tenant__item { justify-content: space-between; }
|
|
387
389
|
.bas-tenant__item.is-active { font-weight: 600; }
|
|
388
390
|
.bas-tenant__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
package/dist/preact.cjs
CHANGED
|
@@ -1352,7 +1352,8 @@ function AnalyticsSeries({ data, t, locale, num }) {
|
|
|
1352
1352
|
] })
|
|
1353
1353
|
] });
|
|
1354
1354
|
}
|
|
1355
|
-
|
|
1355
|
+
var EDGE = 16;
|
|
1356
|
+
function TenantSwitcher({ lang, activeSlug, adapter, onSwitch, roleLabel }) {
|
|
1356
1357
|
const t = TEXT[lang];
|
|
1357
1358
|
const api = hooks.useMemo(() => adapter ?? createFetchTenantAdapter(), [adapter]);
|
|
1358
1359
|
const [rows, setRows] = hooks.useState(null);
|
|
@@ -1361,6 +1362,18 @@ function TenantSwitcher({ lang, activeSlug, adapter, onSwitch }) {
|
|
|
1361
1362
|
const [busy, setBusy] = hooks.useState(null);
|
|
1362
1363
|
const [switchFailed, setSwitchFailed] = hooks.useState(false);
|
|
1363
1364
|
const root = hooks.useRef(null);
|
|
1365
|
+
const menu = hooks.useRef(null);
|
|
1366
|
+
hooks.useLayoutEffect(() => {
|
|
1367
|
+
const el = menu.current;
|
|
1368
|
+
if (!open || !el) return;
|
|
1369
|
+
el.style.transform = "";
|
|
1370
|
+
const r = el.getBoundingClientRect();
|
|
1371
|
+
const vw = document.documentElement.clientWidth || window.innerWidth;
|
|
1372
|
+
let dx = 0;
|
|
1373
|
+
if (r.right > vw - EDGE) dx = vw - EDGE - r.right;
|
|
1374
|
+
if (r.left + dx < EDGE) dx = EDGE - r.left;
|
|
1375
|
+
if (dx !== 0) el.style.transform = `translateX(${Math.round(dx)}px)`;
|
|
1376
|
+
}, [open, rows, loadFailed, switchFailed]);
|
|
1364
1377
|
const load = () => {
|
|
1365
1378
|
setLoadFailed(false);
|
|
1366
1379
|
api.load().then(setRows, () => setLoadFailed(true));
|
|
@@ -1411,7 +1424,7 @@ function TenantSwitcher({ lang, activeSlug, adapter, onSwitch }) {
|
|
|
1411
1424
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-tenant__label", "data-testid": "tenant-switcher-label", children: label })
|
|
1412
1425
|
}
|
|
1413
1426
|
),
|
|
1414
|
-
open ? /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "bas-menu bas-tenant__menu", role: "menu", "data-testid": "tenant-switcher-menu", children: [
|
|
1427
|
+
open ? /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "bas-menu bas-tenant__menu", ref: menu, role: "menu", "data-testid": "tenant-switcher-menu", children: [
|
|
1415
1428
|
loadFailed ? /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "bas-tenant__note", role: "alert", "data-testid": "tenant-switcher-load-error", children: [
|
|
1416
1429
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t.tenantLoadFailed }),
|
|
1417
1430
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", class: "bas-mi", onClick: load, "data-testid": "tenant-switcher-retry", children: t.tenantRetry })
|
|
@@ -1432,7 +1445,7 @@ function TenantSwitcher({ lang, activeSlug, adapter, onSwitch }) {
|
|
|
1432
1445
|
"data-testid": `tenant-switcher-item-${r.tenant.slug}`,
|
|
1433
1446
|
children: [
|
|
1434
1447
|
/* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-tenant__name", children: r.tenant.name }),
|
|
1435
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-tenant__role", children: suspended ? t.tenantSuspended : isActive ? t.tenantActive : r.role })
|
|
1448
|
+
suspended || isActive || roleLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-tenant__role", "data-testid": `tenant-switcher-role-${r.tenant.slug}`, children: suspended ? t.tenantSuspended : isActive ? t.tenantActive : roleLabel(r.role) }) : null
|
|
1436
1449
|
]
|
|
1437
1450
|
},
|
|
1438
1451
|
r.tenant.id
|