website: improvements to the lab UI
1
docs/lab/icons/minimize-black.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="2" fill="#000"/></svg>
|
After Width: | Height: | Size: 122 B |
1
docs/lab/icons/minimize.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="2" fill="#fff"/></svg>
|
After Width: | Height: | Size: 122 B |
1
docs/lab/icons/popup-black.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 3.293l3.354 3.353-.707.708L8 4.707 5.354 7.354l-.708-.708L8 3.293zm0 8L5.354 8.646l-.708.708L8 12.707l3.354-3.353-.707-.708L8 11.293z" fill="#000"/></svg>
|
After Width: | Height: | Size: 281 B |
1
docs/lab/icons/popup.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 3.293l3.354 3.353-.707.708L8 4.707 5.354 7.354l-.708-.708L8 3.293zm0 8L5.354 8.646l-.708.708L8 12.707l3.354-3.353-.707-.708L8 11.293z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 281 B |
1
docs/lab/icons/reset-black.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.993.893L6.95 2.817l1.272.187A6 6 0 112 9h1a5 5 0 105.928-4.914l-.005.032-.79-.116A5.078 5.078 0 008 4v-.018L6.684 3.79l2.214 2.908-.796.606-3.287-4.319L9.459.047l.534.846z" fill="#000"/></svg>
|
After Width: | Height: | Size: 279 B |
1
docs/lab/icons/reset.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.993.893L6.95 2.817l1.272.187A6 6 0 112 9h1a5 5 0 105.928-4.914l-.005.032-.79-.116A5.078 5.078 0 008 4v-.018L6.684 3.79l2.214 2.908-.796.606-3.287-4.319L9.459.047l.534.846z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 279 B |
1
docs/lab/icons/settings-black.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 4H6V3h8v1zM4 4H2V3h2v1zm10 3H6V6h8v1zM4 7H2V6h2v1zm10 3H6V9h8v1zM4 10H2V9h2v1zm10 3H6v-1h8v1zM4 13H2v-1h2v1z" fill="#000"/></svg>
|
After Width: | Height: | Size: 257 B |
1
docs/lab/icons/settings.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 4H6V3h8v1zM4 4H2V3h2v1zm10 3H6V6h8v1zM4 7H2V6h2v1zm10 3H6V9h8v1zM4 10H2V9h2v1zm10 3H6v-1h8v1zM4 13H2v-1h2v1z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 257 B |
@ -32,14 +32,14 @@ if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
<link href="lab.css" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700,700i,900,900i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese">
|
||||
</head>
|
||||
<body class="init-anim">
|
||||
<body class="init-anim varfont">
|
||||
<div id="sidebar-button"></div>
|
||||
<div class="options">
|
||||
|
||||
<div class="flex-x">
|
||||
<label title="Use variable font instead of static font files">
|
||||
<span>VF</span>
|
||||
<input type="checkbox" name="varfont">
|
||||
<input type="checkbox" name="varfont" checked>
|
||||
</label>
|
||||
<label class="italic-setting" title="Italic">
|
||||
<span>I</span>
|
||||
@ -55,30 +55,31 @@ if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="label-and-value">
|
||||
<label class="label-and-value with-slider">
|
||||
<span>Size:</span>
|
||||
<input type="range" value="22" step="1" min="4" max="128" name="_sizeRange">
|
||||
<input type="number" value="22" step="1" min="4" max="1024" name="size">
|
||||
<input type="number" value="22" step="1" min="6" max="1024" name="size">
|
||||
<input type="range" value="22" step="1" min="6" max="256" name="_sizeRange">
|
||||
<!-- <note><span class="unit">dp</span></note> -->
|
||||
</label>
|
||||
|
||||
<!-- Variable font controls (hidden when not using variable fonts) -->
|
||||
<label class="label-and-value varfontControl">
|
||||
<span title="Weight">wght:</span>
|
||||
<input type="range" value="400" step="1" min="100" max="900" name="varWeight">
|
||||
<input type="number" value="400" step="1" min="100" max="900" name="varWeightNum">
|
||||
</label>
|
||||
|
||||
<label class="label-and-value varfontControl">
|
||||
<span title="Slant">slnt:</span>
|
||||
<input type="range" value="0" step="0.01" min="0" max="10" name="varSlant">
|
||||
<input type="number" value="0" step="0.01" min="0" max="10" name="varSlantNum">
|
||||
</label>
|
||||
|
||||
<label class="label-and-value varfontControl">
|
||||
<label class="label-and-value with-slider varfontControl">
|
||||
<span title="Optical size">opsz:</span>
|
||||
<input type="range" value="0" step="0.01" min="16" max="32" name="varOpsz">
|
||||
<input type="number" value="0" step="0.01" min="16" max="32" name="varOpszNum">
|
||||
<input type="number" value="0" step="1" min="14" max="32" name="varOpszNum">
|
||||
<input type="range" value="0" step="0.01" min="14" max="32" name="varOpsz">
|
||||
</label>
|
||||
|
||||
<label class="label-and-value with-slider varfontControl">
|
||||
<span title="Weight">wght:</span>
|
||||
<input type="number" value="400" step="1" min="100" max="900" name="varWeightNum">
|
||||
<input type="range" value="400" step="1" min="100" max="900" name="varWeight">
|
||||
</label>
|
||||
|
||||
<label class="label-and-value with-slider varfontControl">
|
||||
<span title="Slant">slnt:</span>
|
||||
<input type="number" value="0" step="0.1" min="0" max="10" name="varSlantNum">
|
||||
<input type="range" value="0" step="0.01" min="0" max="10" name="varSlant">
|
||||
</label>
|
||||
|
||||
<label class="label-and-value staticfontControl">
|
||||
@ -378,7 +379,7 @@ class BoundVar {
|
||||
|
||||
getValue(ev) {
|
||||
return this.valueGetter ? this.valueGetter(this.e, this.lastValue, ev)
|
||||
: this.isCheckbox ? (this.e.checked || null)
|
||||
: this.isCheckbox ? this.e.checked
|
||||
: this.isNumber ? this.e.valueAsNumber
|
||||
: this.e.value
|
||||
}
|
||||
@ -500,7 +501,7 @@ class Vars {
|
||||
|
||||
refreshValue(name) {
|
||||
let v = this.vars.get(name)
|
||||
return v ? this._refreshValue(v) : null
|
||||
return v === undefined || v === null ? null : this._refreshValue(v)
|
||||
}
|
||||
|
||||
_refreshValue(v, ev) {
|
||||
@ -593,7 +594,9 @@ class Vars {
|
||||
if (v.isNumber) {
|
||||
existingValue = parseFloat(existingValue)
|
||||
} else if (v.isCheckbox) {
|
||||
existingValue = existingValue != '0' && existingValue != 'false' && existingValue != 'off'
|
||||
existingValue = existingValue != '0' &&
|
||||
existingValue != 'false' &&
|
||||
existingValue != 'off'
|
||||
}
|
||||
v.setValue(existingValue)
|
||||
} else {
|
||||
@ -873,7 +876,7 @@ function main() {
|
||||
let varState = {
|
||||
weight: 400, // 400..900
|
||||
slant: 0, // 0..-10
|
||||
opsz: 16, // 16..32
|
||||
opsz: 14, // 14..32
|
||||
}
|
||||
|
||||
function updateVarFont() {
|
||||
@ -927,62 +930,59 @@ function main() {
|
||||
updateVarFont()
|
||||
})
|
||||
|
||||
let varWeightNum = vars.bind('varWeightNum', (e, v) => {
|
||||
let varWeightNum = vars.bind('_wght', '[name="varWeightNum"]', (e, v) => {
|
||||
if (varWeightRange && !varWeightSettingValueImpl)
|
||||
varWeightRange.setValue(v)
|
||||
vars.setValue("wght", v)
|
||||
})
|
||||
|
||||
let varSlantNum = vars.bind('varSlantNum', (e, v) => {
|
||||
let varSlantNum = vars.bind('_slnt', '[name="varSlantNum"]', (e, v) => {
|
||||
if (varSlantRange && !varSlantSettingValueImpl)
|
||||
varSlantRange.setValue(v)
|
||||
vars.setValue("slnt", v)
|
||||
})
|
||||
|
||||
let varOpszNum = vars.bind('varOpszNum', (e, v) => {
|
||||
let varOpszNum = vars.bind('_opsz', '[name="varOpszNum"]', (e, v) => {
|
||||
if (varOpszRange && !varOpszSettingValueImpl)
|
||||
varOpszRange.setValue(v)
|
||||
vars.setValue("opsz", v)
|
||||
})
|
||||
|
||||
varWeightRange = vars.bind('varWeight', (e, v) => {
|
||||
function snapValue(v, factor) {
|
||||
if (shiftKeyPressed && (keyPressed == "" || keyPressed == "Shift"))
|
||||
v = Math.round(v / factor) * factor
|
||||
return v
|
||||
}
|
||||
|
||||
varWeightRange = vars.bind('wght', '[name="varWeight"]', (e, v) => {
|
||||
varState.weight = v
|
||||
varWeightSettingValueImpl = true
|
||||
varWeightNum.setValue(v)
|
||||
varWeightSettingValueImpl = false
|
||||
updateVarFont()
|
||||
}, (e, prevValue, ev) => {
|
||||
if (prevValue === undefined) {
|
||||
if (prevValue === undefined)
|
||||
return 400
|
||||
}
|
||||
v = e.valueAsNumber
|
||||
if (shiftKeyPressed && (keyPressed == "" || keyPressed == "Shift")) {
|
||||
v = Math.round(v / 100) * 100
|
||||
}
|
||||
return v
|
||||
return snapValue(e.valueAsNumber, 100)
|
||||
})
|
||||
|
||||
varSlantRange = vars.bind('varSlant', (e, v) => {
|
||||
varSlantRange = vars.bind('slnt', '[name="varSlant"]', (e, v) => {
|
||||
varState.slant = v
|
||||
varSlantSettingValueImpl = true
|
||||
varSlantNum.setValue(v)
|
||||
varSlantSettingValueImpl = false
|
||||
updateVarFont()
|
||||
}, (e, prevValue, ev) => {
|
||||
if (prevValue === undefined) {
|
||||
if (prevValue === undefined)
|
||||
return 0
|
||||
}
|
||||
return e.valueAsNumber !== undefined ? e.valueAsNumber : e.value
|
||||
return snapValue(e.valueAsNumber, 1)
|
||||
})
|
||||
|
||||
varOpszRange = vars.bind('varOpsz', (e, v) => {
|
||||
varOpszRange = vars.bind('opsz', '[name="varOpsz"]', (e, v) => {
|
||||
varState.opsz = v
|
||||
varOpszSettingValueImpl = true
|
||||
varOpszNum.setValue(v)
|
||||
varOpszSettingValueImpl = false
|
||||
updateVarFont()
|
||||
}, (e, prevValue, ev) => {
|
||||
if (prevValue === undefined) {
|
||||
return 0
|
||||
}
|
||||
return e.valueAsNumber !== undefined ? e.valueAsNumber : e.value
|
||||
return snapValue(e.valueAsNumber, 1)
|
||||
})
|
||||
|
||||
|
||||
|
@ -82,10 +82,10 @@
|
||||
--highlight-bg: #ddd;
|
||||
--guide-color: rgba(255,0,255,0.15);
|
||||
|
||||
--icon-minimize: url(../res/icons/minimize-black.svg);
|
||||
--icon-popup: url(../res/icons/popup-black.svg);
|
||||
--icon-reset: url(../res/icons/reset-black.svg);
|
||||
--icon-settings: url(../res/icons/settings-black.svg);
|
||||
--icon-minimize: url(icons/minimize-black.svg);
|
||||
--icon-popup: url(icons/popup-black.svg);
|
||||
--icon-reset: url(icons/reset-black.svg);
|
||||
--icon-settings: url(icons/settings-black.svg);
|
||||
}
|
||||
|
||||
:root.color-scheme-dark {
|
||||
@ -116,10 +116,10 @@
|
||||
--highlight-bg: #333;
|
||||
--guide-color: rgba(255,100,255,0.15);
|
||||
|
||||
--icon-minimize: url(../res/icons/minimize.svg);
|
||||
--icon-popup: url(../res/icons/popup.svg);
|
||||
--icon-reset: url(../res/icons/reset.svg);
|
||||
--icon-settings: url(../res/icons/settings.svg);
|
||||
--icon-minimize: url(icons/minimize.svg);
|
||||
--icon-popup: url(icons/popup.svg);
|
||||
--icon-reset: url(icons/reset.svg);
|
||||
--icon-settings: url(icons/settings.svg);
|
||||
}
|
||||
|
||||
/* document ———————————————————————————————————————————————————————————————————————————— */
|
||||
@ -129,7 +129,7 @@ body {
|
||||
--fgColorMax: var(--fgColor);
|
||||
background-color: var(--bgColor);
|
||||
color: var(--fgColor);
|
||||
font: 11px var(--font-family), sans-serif;
|
||||
font: 11px var(--font-family),-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
|
||||
font-weight:400; /*300=light, 400=regular, 500=medium, 600=semibold*/
|
||||
transition: all 168ms cubic-bezier(0.17, 0.65, 0.48, 1);
|
||||
transition-property: color, background;
|
||||
@ -175,6 +175,10 @@ label {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
input[type="number"], input[type="text"] {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
width:50px;
|
||||
background: none;
|
||||
@ -183,6 +187,8 @@ input[type="number"] {
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
background: var(--input-color-bg);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
select {
|
||||
@ -200,7 +206,9 @@ select {
|
||||
background-position: right center;
|
||||
}
|
||||
/* fix for Firefox issue:; */
|
||||
select option { font-family:var(--font-family),Inter; }
|
||||
select option {
|
||||
font-family:var(--font-family),Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
|
||||
input[type="number"]:focus,
|
||||
input[type="text"]:focus,
|
||||
@ -444,7 +452,7 @@ body.sidebar-minimized #sidebar-button {
|
||||
background: var(--bgColor);
|
||||
padding: 16px 24px 24px 24px;
|
||||
user-select:none; -moz-user-select: none; -webkit-user-select:none;
|
||||
font-family: var(--font-family), sans-serif;
|
||||
font-family: var(--font-family),-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
|
||||
overflow: auto;
|
||||
letter-spacing:0.012em;
|
||||
transform-origin:100% 0%;
|
||||
@ -492,9 +500,6 @@ body.sidebar-minimized .options {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
/*.options select[name="sample"] {
|
||||
width:225px;
|
||||
}*/
|
||||
.options input::placeholder {
|
||||
color: var(--fgColor);
|
||||
opacity: 0.4;
|
||||
@ -504,10 +509,11 @@ body.sidebar-minimized .options {
|
||||
}
|
||||
.options .label-and-value {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
/*flex-wrap: nowrap;*/
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
height: var(--fieldHeight);
|
||||
min-height: var(--fieldHeight);
|
||||
}
|
||||
.options .label-and-value > *:first-child {
|
||||
flex: 0 0 auto;
|
||||
@ -515,18 +521,26 @@ body.sidebar-minimized .options {
|
||||
text-align: left;
|
||||
margin-right:6px;
|
||||
}
|
||||
.options .label-and-value select {
|
||||
width:90px;
|
||||
}
|
||||
.options .label-and-value input {
|
||||
width: 50px;
|
||||
max-height: var(--fieldHeight);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.options .label-and-value.with-slider input[type="number"] {
|
||||
width: auto;
|
||||
flex: 1 1 auto;
|
||||
border: none;
|
||||
padding: 2px;
|
||||
margin-left: -2px;
|
||||
background: transparent;
|
||||
}
|
||||
.options label input[type="checkbox"] + * {
|
||||
display: inline-block;
|
||||
min-width:50%;
|
||||
}
|
||||
/*.options label input[type="checkbox"] + *:hover {
|
||||
color: var(--fgColorMax);
|
||||
}*/
|
||||
.options label.rasterizePhrase {
|
||||
margin-left:20px;
|
||||
margin-bottom:20px;
|
||||
@ -542,46 +556,39 @@ body.sidebar-minimized .options {
|
||||
.options input[type="checkbox"] + * {
|
||||
user-select: none; -moz-user-select: none; -webkit-user-select:none;
|
||||
}
|
||||
.options .label-and-value.with-slider {
|
||||
display: flex;
|
||||
height: calc(var(--fieldHeight) * 2);
|
||||
margin-bottom: var(--rowBottomMargin);
|
||||
}
|
||||
.options .varfontControl,
|
||||
.options .staticfontControl {
|
||||
transition: all 168ms cubic-bezier(0.17, 0.65, 0.48, 1);
|
||||
transition-property: opacity, height, margin;
|
||||
}
|
||||
.options .varfontControl,
|
||||
.options .label-and-value.with-slider.varfontControl,
|
||||
body.varfont .options .staticfontControl {
|
||||
display: block;
|
||||
pointer-events:none;
|
||||
overflow: hidden;
|
||||
opacity:0;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
margin: 0;
|
||||
}
|
||||
body.varfont .options .varfontControl {
|
||||
body.varfont .options .label-and-value.with-slider.varfontControl {
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
pointer-events:all;
|
||||
opacity:1;
|
||||
height: var(--fieldHeight);
|
||||
height: calc(var(--fieldHeight) * 2);
|
||||
margin-bottom: var(--rowBottomMargin);
|
||||
}
|
||||
/*body.varfont .options .staticfontControl {
|
||||
display: none;
|
||||
}*/
|
||||
.options .varfontControl .label-and-value {
|
||||
display: flex;
|
||||
}
|
||||
/*body.varfont .options select[name="weight"] {
|
||||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}*/
|
||||
.options input[type="range"] {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.options input[type="range"] + input[type="number"] {
|
||||
flex: 0 1 auto;
|
||||
width: 40px;
|
||||
border: none;
|
||||
padding: 2px;
|
||||
margin-left: 4px;
|
||||
background: transparent;
|
||||
.options input[type="number"] + input[type="range"] {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
.options .label-and-value input + note,
|
||||
.options .label-and-value select + note {
|
||||
|