@broberg/app-shell 0.11.0 → 0.11.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/README.md +11 -1
- package/css/app-shell.css +7 -7
- package/dist/preact.cjs +29 -1
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.js +29 -1
- package/dist/preact.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,16 @@ 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.11.1 — the palette list floats over the menu (F001.25)
|
|
57
|
+
|
|
58
|
+
Christian 10/10: «Kunne denne ikke være en pop-over ting så dialogen ikke bliver
|
|
59
|
+
forstørret hver gang man klikker på listen?» The list is now a popover
|
|
60
|
+
(`position: fixed`, placed from the button): the menu keeps its height and
|
|
61
|
+
nothing below moves. It opens below the button, upward when there is no room,
|
|
62
|
+
stays inside the viewport, and closes when the menu scrolls or the window
|
|
63
|
+
resizes. testids and keys unchanged. Rendering moved: the open list no longer
|
|
64
|
+
pushes «Flader» and the rest down.
|
|
65
|
+
|
|
56
66
|
## 0.11.0 — the user menu's Appearance, tidied (F001.23)
|
|
57
67
|
|
|
58
68
|
Christian 10/10, via appkit: «Neuroner … er reelt set kun til trail og cardmem» and «Paletten er ikke pæn».
|
|
@@ -68,7 +78,7 @@ Christian 10/10, via appkit: «Neuroner … er reelt set kun til trail og cardme
|
|
|
68
78
|
- **Palette is a dropdown**, not four wrapping buttons. Custom, not a native
|
|
69
79
|
`<select>` (D-4cd764): arrows open and move, Enter/Space choose, Escape closes
|
|
70
80
|
the list without choosing and leaves the menu open; a second Escape closes the
|
|
71
|
-
menu.
|
|
81
|
+
menu. (0.11.1: it floats over the menu as a popover.)
|
|
72
82
|
testids: `user-menu-palette` (the button), `user-menu-palette-list`,
|
|
73
83
|
`user-menu-palette-<id>` (each option). **A Lens flow that clicked
|
|
74
84
|
`user-menu-palette-<id>` directly must click `user-menu-palette` first.**
|
package/css/app-shell.css
CHANGED
|
@@ -298,11 +298,10 @@
|
|
|
298
298
|
}
|
|
299
299
|
.bas-seg > button[aria-pressed="true"] { background: var(--olive-btn); color: var(--paper, var(--bg-card)); }
|
|
300
300
|
.bas-seg > button:not([aria-pressed="true"]):hover { color: var(--fg); }
|
|
301
|
-
/* F001.23 — the palette dropdown. The list
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
.bas-
|
|
305
|
-
.bas-dd { display: contents; }
|
|
301
|
+
/* F001.23/F001.25 — the palette dropdown. The list is a POPOVER (position
|
|
302
|
+
fixed, placed from the button in JS), so opening it neither grows the menu
|
|
303
|
+
nor gets clipped by its overflow. */
|
|
304
|
+
.bas-dd { position: relative; display: inline-flex; }
|
|
306
305
|
.bas-dd__btn {
|
|
307
306
|
display: inline-flex; align-items: center; gap: 8px; min-width: 120px; justify-content: space-between;
|
|
308
307
|
font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; font-weight: 500; padding: 5px 10px;
|
|
@@ -313,8 +312,9 @@
|
|
|
313
312
|
.bas-dd__btn[aria-expanded="true"] .bas-dd__caret { transform: rotate(180deg); }
|
|
314
313
|
.bas-dd__caret { color: var(--fg-muted); transition: transform .12s; }
|
|
315
314
|
.bas-dd__list {
|
|
316
|
-
|
|
317
|
-
border-radius: var(--bas-radius); background: var(--bg-
|
|
315
|
+
z-index: 70; list-style: none; margin: 0; padding: 4px; max-height: min(60vh, 320px); overflow-y: auto;
|
|
316
|
+
border-radius: var(--bas-radius); background: var(--bg-card); border: 1px solid var(--border);
|
|
317
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
|
|
318
318
|
}
|
|
319
319
|
.bas-dd__opt { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: calc(var(--bas-radius) - 2px); font-size: 12.5px; color: var(--fg); cursor: pointer; }
|
|
320
320
|
.bas-dd__opt.is-active { background: var(--hover); }
|
package/dist/preact.cjs
CHANGED
|
@@ -847,6 +847,33 @@ function Segmented(props) {
|
|
|
847
847
|
}
|
|
848
848
|
function Dropdown(props) {
|
|
849
849
|
const [state, setState] = hooks.useState({ open: false, highlighted: -1 });
|
|
850
|
+
const btnRef = hooks.useRef(null);
|
|
851
|
+
const listRef = hooks.useRef(null);
|
|
852
|
+
const [pos, setPos] = hooks.useState(void 0);
|
|
853
|
+
hooks.useLayoutEffect(() => {
|
|
854
|
+
if (!state.open || !btnRef.current) return setPos(void 0);
|
|
855
|
+
const r = btnRef.current.getBoundingClientRect();
|
|
856
|
+
const vw = window.innerWidth, vh = window.innerHeight, m = 8;
|
|
857
|
+
const h = listRef.current?.offsetHeight ?? 0;
|
|
858
|
+
const width = Math.min(Math.max(r.width, 160), vw - 2 * m);
|
|
859
|
+
const left = Math.max(m, Math.min(r.right - width, vw - width - m));
|
|
860
|
+
const below = r.bottom + 4;
|
|
861
|
+
const top = below + h <= vh - m || r.top - 4 - h < m ? Math.min(below, vh - m - h) : r.top - 4 - h;
|
|
862
|
+
setPos({ position: "fixed", left: `${left}px`, top: `${Math.max(m, top)}px`, width: `${width}px` });
|
|
863
|
+
}, [state.open]);
|
|
864
|
+
hooks.useEffect(() => {
|
|
865
|
+
if (!state.open) return;
|
|
866
|
+
const close = (e) => {
|
|
867
|
+
if (e.target instanceof Node && listRef.current?.contains(e.target)) return;
|
|
868
|
+
setState((st) => ({ ...st, open: false }));
|
|
869
|
+
};
|
|
870
|
+
window.addEventListener("scroll", close, true);
|
|
871
|
+
window.addEventListener("resize", close);
|
|
872
|
+
return () => {
|
|
873
|
+
window.removeEventListener("scroll", close, true);
|
|
874
|
+
window.removeEventListener("resize", close);
|
|
875
|
+
};
|
|
876
|
+
}, [state.open]);
|
|
850
877
|
const current = Math.max(0, props.options.findIndex(([v]) => v === props.value));
|
|
851
878
|
const choose = (i) => {
|
|
852
879
|
setState({ open: false, highlighted: i });
|
|
@@ -867,6 +894,7 @@ function Dropdown(props) {
|
|
|
867
894
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
868
895
|
"button",
|
|
869
896
|
{
|
|
897
|
+
ref: btnRef,
|
|
870
898
|
type: "button",
|
|
871
899
|
class: "bas-dd__btn",
|
|
872
900
|
"data-testid": props.testid,
|
|
@@ -882,7 +910,7 @@ function Dropdown(props) {
|
|
|
882
910
|
]
|
|
883
911
|
}
|
|
884
912
|
),
|
|
885
|
-
state.open ? /* @__PURE__ */ jsxRuntime.jsx("ul", { class: "bas-dd__list", role: "listbox", "aria-label": props.label, "data-testid": `${props.testid}-list`, children: props.options.map(([v, label], i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
913
|
+
state.open ? /* @__PURE__ */ jsxRuntime.jsx("ul", { ref: listRef, class: "bas-dd__list", style: pos ?? { position: "fixed", visibility: "hidden" }, role: "listbox", "aria-label": props.label, "data-testid": `${props.testid}-list`, children: props.options.map(([v, label], i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
886
914
|
"li",
|
|
887
915
|
{
|
|
888
916
|
id: optId(v),
|