v0.3.02-beta: maak tekenwerkbalk compact
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 9s
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 9s
This commit is contained in:
parent
09a5d84bba
commit
d864299ea6
5 changed files with 142 additions and 21 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.3.01-beta
|
||||
0.3.02-beta
|
||||
|
|
|
|||
|
|
@ -1267,3 +1267,46 @@ body.dark .dock-item:hover{background:var(--surface-3);}
|
|||
body.dark .wp-group button.on{background:var(--surface-3); box-shadow:none;}
|
||||
body.dark .lg-kbd button,body.dark .blok{filter:saturate(.9) brightness(.96);}
|
||||
body.dark .bs-card canvas{background:#fff;} /* bord-preview blijft de echte (witte) bordkleur tonen */
|
||||
|
||||
|
||||
/* ---------- compacte tekenwerkbalk met selectie-popovers ---------- */
|
||||
#penbar{flex-wrap:nowrap; gap:4px; overflow:visible;}
|
||||
.pen-picker{position:relative; flex:none;}
|
||||
.pen-current{
|
||||
width:42px; height:32px; padding:0 5px; border:1px solid transparent; border-radius:9px;
|
||||
background:var(--surface-2); color:var(--ink); cursor:pointer; display:flex;
|
||||
align-items:center; justify-content:center; gap:3px; font:inherit;
|
||||
}
|
||||
.pen-current:hover,.pen-picker.open .pen-current{background:var(--surface-3); border-color:var(--line);}
|
||||
.pen-current-value{font-size:16px; line-height:1; min-width:18px; text-align:center;}
|
||||
.pen-caret{font-size:8px; color:var(--muted); transform:rotate(0); transition:transform .15s;}
|
||||
.pen-picker.open .pen-caret{transform:rotate(180deg);}
|
||||
.pen-current-color{width:18px; height:18px; border-radius:50%; box-shadow:inset 0 0 0 1px rgba(0,0,0,.16);}
|
||||
.pen-current-size{display:block; border-radius:50%; background:var(--ink);}
|
||||
.pen-current-bg{width:19px; height:19px; display:block; border:1.5px solid #9db6d8; border-radius:4px; background:#fff;}
|
||||
.pen-current-bg.bg-dots{background-image:radial-gradient(circle,#9db6d8 1px,transparent 1px); background-size:5px 5px;}
|
||||
.pen-current-bg.bg-lines{background-image:repeating-linear-gradient(#0000 0 4px,#9db6d8 4px 5px);}
|
||||
.pen-current-bg.bg-write{background-image:repeating-linear-gradient(#0000 0 2px,#c3d5ec 2px 3px,#0000 3px 5px,#6d92c4 5px 6px);}
|
||||
.pen-current-bg.bg-grid-s{background-image:repeating-linear-gradient(#0000 0 4px,#9db6d8 4px 5px),repeating-linear-gradient(90deg,#0000 0 4px,#9db6d8 4px 5px);}
|
||||
.pen-current-bg.bg-grid-b{background-image:repeating-linear-gradient(#0000 0 8px,#9db6d8 8px 9px),repeating-linear-gradient(90deg,#0000 0 8px,#9db6d8 8px 9px);}
|
||||
#penbar .pen-popover{
|
||||
display:none; position:absolute; left:50%; bottom:calc(100% + 10px); transform:translateX(-50%);
|
||||
z-index:20; width:max-content; max-width:min(300px,calc(100vw - 24px)); padding:7px;
|
||||
background:var(--surface); border:1px solid var(--line); border-radius:12px;
|
||||
box-shadow:var(--shadow-2); gap:5px;
|
||||
}
|
||||
#penbar .pen-picker.open>.pen-popover{display:flex;}
|
||||
#penbar .pen-color-popover{width:210px; flex-direction:column; align-items:stretch;}
|
||||
#penbar .pen-color-popover .wp-group{display:grid; grid-template-columns:repeat(6,28px); background:transparent; padding:0;}
|
||||
.pen-pop-label{font-size:10px; font-weight:800; color:var(--muted); text-transform:uppercase; letter-spacing:.45px; margin:2px 2px 0;}
|
||||
.pen-custom{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:3px; padding-top:7px; border-top:1px solid var(--line); font-size:12px; font-weight:700;}
|
||||
.pen-custom input{width:34px; height:26px; padding:0; border:0; border-radius:7px; background:transparent; cursor:pointer;}
|
||||
#hud.vert #penbar .pen-popover{left:calc(100% + 10px); bottom:auto; top:50%; transform:translateY(-50%);}
|
||||
#hud.vert #penbar .pen-color-popover{display:none;}
|
||||
#hud.vert #penbar .pen-picker.open>.pen-color-popover{display:flex;}
|
||||
body.hc #penbar .pen-current,body.hc #penbar .pen-popover{border:2px solid #000;}
|
||||
@media (max-width:600px),(pointer:coarse){
|
||||
#penbar{gap:3px;}
|
||||
.pen-current{width:40px; height:36px;}
|
||||
#penbar .pen-popover{position:fixed; left:50%; bottom:70px; transform:translateX(-50%);}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,11 +43,32 @@
|
|||
<button class="hud-btn hud-orient">⇄</button>
|
||||
<button class="hud-btn hud-min">–</button>
|
||||
<div id="penbar">
|
||||
<div class="wp-group pen-tools"></div>
|
||||
<div class="pen-picker" data-picker="tools">
|
||||
<button class="pen-current" type="button" aria-expanded="false"><span class="pen-current-value">✏️</span><span class="pen-caret">⌃</span></button>
|
||||
<div class="wp-group pen-tools pen-popover"></div>
|
||||
</div>
|
||||
<div class="pen-picker" data-picker="colors">
|
||||
<button class="pen-current" type="button" aria-expanded="false"><i class="pen-current-color"></i><span class="pen-caret">⌃</span></button>
|
||||
<div class="pen-popover pen-color-popover">
|
||||
<div class="pen-pop-label pen-recent-label"></div>
|
||||
<div class="wp-group pen-recent"></div>
|
||||
<div class="pen-pop-label pen-palette-label"></div>
|
||||
<div class="wp-group pen-colors"></div>
|
||||
<div class="wp-group pen-sizes"></div>
|
||||
<div class="wp-group pen-bgs"></div>
|
||||
<div class="wp-group pen-extras"></div>
|
||||
<label class="pen-custom"><span class="pen-custom-label"></span><input type="color" value="#26344a"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pen-picker" data-picker="sizes">
|
||||
<button class="pen-current" type="button" aria-expanded="false"><i class="pen-current-size"></i><span class="pen-caret">⌃</span></button>
|
||||
<div class="wp-group pen-sizes pen-popover"></div>
|
||||
</div>
|
||||
<div class="pen-picker" data-picker="backgrounds">
|
||||
<button class="pen-current" type="button" aria-expanded="false"><i class="pen-current-bg"></i><span class="pen-caret">⌃</span></button>
|
||||
<div class="wp-group pen-bgs pen-popover"></div>
|
||||
</div>
|
||||
<div class="pen-picker" data-picker="extras">
|
||||
<button class="pen-current" type="button" aria-expanded="false"><span class="pen-current-value">•••</span><span class="pen-caret">⌃</span></button>
|
||||
<div class="wp-group pen-extras pen-popover"></div>
|
||||
</div>
|
||||
<button class="wp-clear pen-clear">🗑</button>
|
||||
<button class="wp-clear pen-close">✕</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -277,8 +277,51 @@ new ResizeObserver(bResize).observe(board);
|
|||
bResize();
|
||||
|
||||
const PEN = { tool:"pen", color:"#26344a", size:4, nib:4 };
|
||||
const DEFAULT_PEN_COLORS = ["#26344a","#3b7dd8","#e0554d","#3fae6a","#9b59b6","#f7c948"];
|
||||
const RECENT_COLOR_KEY = "teachRecentPenColors";
|
||||
let recentPenColors = [];
|
||||
try{ recentPenColors = JSON.parse(localStorage.getItem(RECENT_COLOR_KEY) || "[]").filter(c=>/^#[0-9a-f]{6}$/i.test(c)).slice(0,6); }catch(e){}
|
||||
const BOARD = { bg:"blank" };
|
||||
const penbar = document.getElementById("penbar");
|
||||
function closePenPickers(except){
|
||||
penbar.querySelectorAll(".pen-picker.open").forEach(p=>{
|
||||
if(p===except) return;
|
||||
p.classList.remove("open");
|
||||
p.querySelector(".pen-current").setAttribute("aria-expanded","false");
|
||||
});
|
||||
}
|
||||
penbar.querySelectorAll(".pen-picker").forEach(p=>{
|
||||
p.querySelector(".pen-current").addEventListener("click", e=>{
|
||||
e.stopPropagation();
|
||||
const open = !p.classList.contains("open");
|
||||
closePenPickers();
|
||||
p.classList.toggle("open", open);
|
||||
p.querySelector(".pen-current").setAttribute("aria-expanded", String(open));
|
||||
});
|
||||
});
|
||||
document.addEventListener("pointerdown", e=>{ if(!e.target.closest(".pen-picker")) closePenPickers(); });
|
||||
function makeColorButton(c, host){
|
||||
const b = document.createElement("button");
|
||||
b.className = "wp-color"; b.dataset.c = c; b.type = "button";
|
||||
const dot = document.createElement("i"); dot.style.background = c;
|
||||
b.appendChild(dot);
|
||||
b.addEventListener("click", ()=>selectPenColor(c));
|
||||
host.appendChild(b);
|
||||
}
|
||||
function renderRecentPenColors(){
|
||||
const host = penbar.querySelector(".pen-recent");
|
||||
host.innerHTML = "";
|
||||
recentPenColors.forEach(c=>makeColorButton(c, host));
|
||||
penbar.querySelector(".pen-recent-label").hidden = recentPenColors.length===0;
|
||||
host.hidden = recentPenColors.length===0;
|
||||
}
|
||||
function selectPenColor(c){
|
||||
PEN.color = c.toLowerCase();
|
||||
if(PEN.tool==="erase") PEN.tool = "pen";
|
||||
recentPenColors = [PEN.color, ...recentPenColors.filter(x=>x!==PEN.color)].slice(0,6);
|
||||
try{ localStorage.setItem(RECENT_COLOR_KEY, JSON.stringify(recentPenColors)); }catch(e){}
|
||||
renderRecentPenColors(); closePenPickers(); refreshPenbar();
|
||||
}
|
||||
function setPen(on){
|
||||
document.body.classList.toggle("pen", on);
|
||||
document.body.classList.toggle("pen-text", on && PEN.tool==="text");
|
||||
|
|
@ -295,24 +338,18 @@ const PEN_TOOLS = [["hand","✋","toolHand"],["pen","✏️","toolPen"],["vulp",
|
|||
PEN_TOOLS.forEach(([id,icon])=>{
|
||||
const b = document.createElement("button");
|
||||
b.dataset.tool = id; b.textContent = icon;
|
||||
b.addEventListener("click", ()=>{ PEN.tool = id; setPen(true); refreshPenbar(); });
|
||||
b.addEventListener("click", ()=>{ PEN.tool = id; setPen(true); closePenPickers(); refreshPenbar(); });
|
||||
penbar.querySelector(".pen-tools").appendChild(b);
|
||||
});
|
||||
["#26344a","#3b7dd8","#e0554d","#3fae6a","#9b59b6","#f7c948"].forEach(c=>{
|
||||
const b = document.createElement("button");
|
||||
b.className = "wp-color"; b.dataset.c = c;
|
||||
const dot = document.createElement("i"); dot.style.background = c;
|
||||
b.appendChild(dot);
|
||||
b.addEventListener("click", ()=>{ PEN.color = c; if(PEN.tool==="erase") PEN.tool = "pen"; refreshPenbar(); });
|
||||
penbar.querySelector(".pen-colors").appendChild(b);
|
||||
});
|
||||
DEFAULT_PEN_COLORS.forEach(c=>makeColorButton(c, penbar.querySelector(".pen-colors")));
|
||||
renderRecentPenColors();
|
||||
[3,5,8].forEach(s=>{
|
||||
const b = document.createElement("button");
|
||||
b.className = "wp-size"; b.dataset.s = s;
|
||||
const i = document.createElement("i");
|
||||
i.style.width = i.style.height = (s+4)+"px";
|
||||
b.appendChild(i);
|
||||
b.addEventListener("click", ()=>{ PEN.size = s; refreshPenbar(); });
|
||||
b.addEventListener("click", ()=>{ PEN.size = s; closePenPickers(); refreshPenbar(); });
|
||||
penbar.querySelector(".pen-sizes").appendChild(b);
|
||||
});
|
||||
const PEN_BGS = [["blank","bgBlank"],["dots","bgDots"],["lines","bgLines"],["write","bgWrite"],["grid-s","bgGridS"],["grid-b","bgGridB"]];
|
||||
|
|
@ -320,16 +357,19 @@ PEN_BGS.forEach(([id])=>{
|
|||
const b = document.createElement("button");
|
||||
b.className = "wp-bg"; b.dataset.bg = id;
|
||||
b.appendChild(document.createElement("i"));
|
||||
b.addEventListener("click", ()=>setBoardBg(id));
|
||||
b.addEventListener("click", ()=>{ setBoardBg(id); closePenPickers(); });
|
||||
penbar.querySelector(".pen-bgs").appendChild(b);
|
||||
});
|
||||
const PEN_EXTRAS = [["ruler","📏","toolRuler"],["geo","📐","toolGeo"],["lens","🔍","toolLens"],["light","🚦","wg_light"]];
|
||||
PEN_EXTRAS.forEach(([id,icon])=>{
|
||||
const b = document.createElement("button");
|
||||
b.dataset.extra = id; b.textContent = icon;
|
||||
b.addEventListener("click", ()=>toggleDTool(id));
|
||||
b.addEventListener("click", ()=>{ toggleDTool(id); closePenPickers(); });
|
||||
penbar.querySelector(".pen-extras").appendChild(b);
|
||||
});
|
||||
const customPenColor = penbar.querySelector(".pen-custom input");
|
||||
customPenColor.addEventListener("input", ()=>selectPenColor(customPenColor.value));
|
||||
customPenColor.addEventListener("click", e=>e.stopPropagation());
|
||||
penbar.querySelector(".pen-clear").addEventListener("click", ()=>bCtx.clearRect(0,0,bInk.width,bInk.height));
|
||||
/* the ✍-button toggles drawing mode on/off (palette itself stays visible) */
|
||||
penbar.querySelector(".pen-close").addEventListener("click", ()=>setPen(!document.body.classList.contains("pen")));
|
||||
|
|
@ -367,6 +407,23 @@ function updateHud(){ hud.classList.toggle("has-dock", dock.children.length > 0)
|
|||
new MutationObserver(updateHud).observe(dock, {childList:true});
|
||||
updateHud();
|
||||
function refreshPenbar(){
|
||||
const toolDef = PEN_TOOLS.find(x=>x[0]===PEN.tool);
|
||||
penbar.querySelector('[data-picker="tools"] .pen-current-value').textContent = toolDef[1];
|
||||
penbar.querySelector('[data-picker="tools"] .pen-current').title = T(toolDef[2]);
|
||||
const currentColor = penbar.querySelector(".pen-current-color");
|
||||
currentColor.style.background = PEN.color;
|
||||
penbar.querySelector('[data-picker="colors"] .pen-current').title = T("penColor");
|
||||
const currentSize = penbar.querySelector(".pen-current-size");
|
||||
currentSize.style.width = currentSize.style.height = (PEN.size+4)+"px";
|
||||
penbar.querySelector('[data-picker="sizes"] .pen-current').title = T("penSize");
|
||||
const currentBg = penbar.querySelector(".pen-current-bg");
|
||||
currentBg.className = "pen-current-bg bg-"+BOARD.bg;
|
||||
penbar.querySelector('[data-picker="backgrounds"] .pen-current').title = T(PEN_BGS.find(x=>x[0]===BOARD.bg)[1]);
|
||||
penbar.querySelector('[data-picker="extras"] .pen-current').title = T("penExtras");
|
||||
penbar.querySelector(".pen-recent-label").textContent = T("recentColors");
|
||||
penbar.querySelector(".pen-palette-label").textContent = T("paletteColors");
|
||||
penbar.querySelector(".pen-custom-label").textContent = T("customColor");
|
||||
customPenColor.value = PEN.color;
|
||||
penbar.querySelectorAll(".pen-tools button").forEach(b=>{
|
||||
b.classList.toggle("on", b.dataset.tool===PEN.tool);
|
||||
b.title = T(PEN_TOOLS.find(x=>x[0]===b.dataset.tool)[2]);
|
||||
|
|
|
|||
|
|
@ -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.01-beta";
|
||||
const VERSION = "0.3.02-beta";
|
||||
(function(){
|
||||
const tag = document.getElementById("verTag");
|
||||
tag.textContent = "v"+VERSION;
|
||||
|
|
@ -38,7 +38,7 @@ const I18N = {
|
|||
wg_write:"Schrijfblad", wg_write_d:"Schrijven en rekenen: pen, gum en papier met schrijflijnen of rekenblokjes.",
|
||||
bgBlank:"Leeg blad", bgLines:"Lijntjes", bgWrite:"Schrijflijnen",
|
||||
bgGridS:"Kleine rekenblokjes", bgGridB:"Grote rekenblokjes",
|
||||
penSize:"Dikte", eraser:"Gum", clearAll:"Alles wissen",
|
||||
penSize:"Dikte", penColor:"Kleur", penExtras:"Hulpmiddelen", recentColors:"Recent gebruikt", paletteColors:"Kleuren", customColor:"Eigen kleur", eraser:"Gum", clearAll:"Alles wissen",
|
||||
toolPen:"Pen", toolFountain:"Vulpen (dun en dik, reageert op druk of snelheid)",
|
||||
toolMark:"Markeerstift", toolText:"Tekst typen (klik op het blad)",
|
||||
wMin:"Minimaliseren", wMax:"Herstellen",
|
||||
|
|
@ -178,7 +178,7 @@ const I18N = {
|
|||
wg_write:"Writing pad", wg_write_d:"Writing and maths: pen, eraser and paper with handwriting lines or maths squares.",
|
||||
bgBlank:"Blank sheet", bgLines:"Lines", bgWrite:"Handwriting lines",
|
||||
bgGridS:"Small maths squares", bgGridB:"Big maths squares",
|
||||
penSize:"Thickness", eraser:"Eraser", clearAll:"Clear all",
|
||||
penSize:"Thickness", penColor:"Colour", penExtras:"Tools", recentColors:"Recently used", paletteColors:"Colours", customColor:"Custom colour", eraser:"Eraser", clearAll:"Clear all",
|
||||
toolPen:"Pen", toolFountain:"Fountain pen (thin and thick, follows pressure or speed)",
|
||||
toolMark:"Highlighter", toolText:"Type text (click the sheet)",
|
||||
wMin:"Minimize", wMax:"Restore",
|
||||
|
|
|
|||
Loading…
Reference in a new issue