feat: sluitknop op geminimaliseerde widgets in de dock (v0.3.63-beta)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 45s
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 45s
- Elke dock-pil (geminimaliseerde widget) heeft nu een eigen ✕ om de widget direct te sluiten, zonder hem eerst terug op het bord te zetten - Klik op de pil zelf blijft de widget herstellen; de ✕ deelt hetzelfde sluitpad als de ✕ in de widgetkop - Groter tikvlak voor de ✕ op aanraakschermen; titels wisselen mee met de taal - Geverifieerd in headless Chromium (8 checks, incl. serialisatie na sluiten/herstellen) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0149FgUQvuwxKKEdvQGmNngF
This commit is contained in:
parent
87b22efc56
commit
7bd35685fe
4 changed files with 44 additions and 11 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.3.62-beta
|
||||
0.3.63-beta
|
||||
|
|
|
|||
|
|
@ -460,6 +460,16 @@
|
|||
}
|
||||
.dock-item:hover{background:var(--surface-2); transform:translateY(-2px);}
|
||||
.dock-item .di{font-size:16px; line-height:1;}
|
||||
/* sluitknop op de dock-pil: geminimaliseerde widgets zijn direct te sluiten */
|
||||
.dock-item .dock-close{
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
width:20px; height:20px; margin:-2px -6px -2px 0; border-radius:7px;
|
||||
font-size:11px; color:var(--muted); line-height:1;
|
||||
}
|
||||
.dock-item .dock-close:hover{background:var(--red-soft); color:var(--red);}
|
||||
@media (pointer:coarse){
|
||||
.dock-item .dock-close{width:28px; height:28px;}
|
||||
}
|
||||
.widget-head{
|
||||
display:flex; align-items:center; gap:10px; padding:10px 14px;
|
||||
background:rgba(255,255,255,.4); border-bottom:1px solid rgba(150,170,200,.28);
|
||||
|
|
|
|||
|
|
@ -60,12 +60,24 @@ const REGISTRY = [
|
|||
];
|
||||
const WIDGET_CATS = [["favorites","galleryFavorites"],["taal","catTaal"],["rekenen","catRekenen"],["class","catClass"],["tools","catTools"],["media","catMedia"]];
|
||||
|
||||
/* houdt een (opgeslagen of standaard) widgetgrootte binnen het bord - zonder
|
||||
dit passen desktop-formaten (tot 760px breed) niet op een telefoon/tablet */
|
||||
/* houdt een (opgeslagen of standaard) widgetgrootte binnen het bord. Op een
|
||||
telefoon is de beschikbare ruimte leidend: een desktop-minimum van bv.
|
||||
640px mag daar niet alsnog horizontale overflow afdwingen. */
|
||||
function widgetSizeBounds(def, left=0, top=0){
|
||||
const maxW = Math.max(1, board.clientWidth - left - 8);
|
||||
const maxH = Math.max(1, board.clientHeight - top - 8);
|
||||
return {
|
||||
minW: Math.min(def.minW || 240, maxW),
|
||||
minH: Math.min(def.minH || 180, maxH),
|
||||
maxW, maxH,
|
||||
};
|
||||
}
|
||||
function clampWidgetSize(w, h, def){
|
||||
const fw = Math.max(def.minW || 240, Math.min(w, board.clientWidth));
|
||||
const fh = Math.max(def.minH || 180, Math.min(h, board.clientHeight));
|
||||
return { w: fw, h: fh };
|
||||
const {minW,minH,maxW,maxH} = widgetSizeBounds(def);
|
||||
return {
|
||||
w: Math.max(minW, Math.min(w, maxW)),
|
||||
h: Math.max(minH, Math.min(h, maxH)),
|
||||
};
|
||||
}
|
||||
|
||||
/* stabiel widget-instantie-id, zelfde patroon als genBoardId() verderop - nodig
|
||||
|
|
@ -148,9 +160,14 @@ function makeWidget(def, saved){
|
|||
win.style.display = "none";
|
||||
pill = document.createElement("button");
|
||||
pill.className = "dock-item";
|
||||
pill.innerHTML = `<span class="di">${def.icon}</span><span class="dl"></span>`;
|
||||
pill.innerHTML = `<span class="di">${def.icon}</span><span class="dl"></span><span class="dock-close" role="button">✕</span>`;
|
||||
pill.querySelector(".dl").textContent = T("wg_"+def.id);
|
||||
pill.title = T("wMax");
|
||||
/* ook een geminimaliseerde widget is direct te sluiten, zonder hem
|
||||
eerst terug op het bord te hoeven zetten */
|
||||
const x = pill.querySelector(".dock-close");
|
||||
x.title = T("close");
|
||||
x.addEventListener("click", e=>{ e.stopPropagation(); removeWidget(); });
|
||||
pill.addEventListener("click", ()=>setMin(false));
|
||||
dock.appendChild(pill);
|
||||
}else if(!m && pill){
|
||||
|
|
@ -206,7 +223,11 @@ function makeWidget(def, saved){
|
|||
minBtn.title = T("wMin");
|
||||
maxBtn.title = T(win.dataset.max==="1" ? "wUnfull" : "wFull");
|
||||
zBtn.title = T("wZoom");
|
||||
if(pill){ pill.querySelector(".dl").textContent = T("wg_"+def.id); pill.title = T("wMax"); }
|
||||
if(pill){
|
||||
pill.querySelector(".dl").textContent = T("wg_"+def.id);
|
||||
pill.title = T("wMax");
|
||||
pill.querySelector(".dock-close").title = T("close");
|
||||
}
|
||||
};
|
||||
setTitle();
|
||||
document.addEventListener("langchange", setTitle);
|
||||
|
|
@ -233,11 +254,13 @@ function makeWidget(def, saved){
|
|||
dupBtn.title=T("widgetDuplicate");dupBtn.setAttribute("aria-label",dupBtn.title);previewBtn.title=T("widgetPreview");previewBtn.setAttribute("aria-label",previewBtn.title);
|
||||
dupBtn.addEventListener("click",()=>makeWidget(def,{x:win.offsetLeft+28,y:win.offsetTop+28,w:win.offsetWidth,h:win.offsetHeight,wz:+win.dataset.wz||1,state:api.getState?structuredClone(api.getState()):null}));
|
||||
instances.add(inst);
|
||||
close.addEventListener("click", ()=>{
|
||||
/* gedeeld sluitpad voor de ✕ in de widgetkop én de ✕ op de dock-pil */
|
||||
function removeWidget(){
|
||||
markBoardChange();
|
||||
if(pill){ pill.remove(); pill = null; }
|
||||
instances.delete(inst); win.remove(); updateEmptyHint();
|
||||
});
|
||||
}
|
||||
close.addEventListener("click", removeWidget);
|
||||
updateEmptyHint();
|
||||
markBoardChange();
|
||||
return inst;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"use strict";
|
||||
/* version — shown until /api/version resolves (or if the fetch fails, e.g. offline).
|
||||
Kept in sync by hand with the VERSION file at the repo root on every release. */
|
||||
const VERSION = "0.3.62-beta";
|
||||
const VERSION = "0.3.63-beta";
|
||||
(function(){
|
||||
const tag = document.getElementById("verTag");
|
||||
tag.textContent = "v"+VERSION;
|
||||
|
|
|
|||
Loading…
Reference in a new issue