Skip to content

Commit

Permalink
Merge pull request #808 from googlefonts/info-range-slider
Browse files Browse the repository at this point in the history
Replace use of 'raw' range input with our range-slider
  • Loading branch information
justvanrossum authored Sep 14, 2023
2 parents ab69c76 + f417703 commit e0cac56
Showing 1 changed file with 40 additions and 172 deletions.
212 changes: 40 additions & 172 deletions src/fontra/client/web-components/ui-form.js
Original file line number Diff line number Diff line change
@@ -1,129 +1,20 @@
import { QueueIterator } from "../core/queue-iterator.js";
import { hyphenatedToCamelCase, round } from "../core/utils.js";
import { hyphenatedToCamelCase } from "../core/utils.js";
import { SimpleElement } from "../core/unlit.js";
import * as html from "../core/unlit.js";
import { themeColorCSS } from "./theme-support.js";

const colors = {
"ui-form-input-foreground-color": ["black", "white"],
"ui-form-input-background-color": ["white", "#333"],
"ui-form-input-border-color": ["#888", "#222"],
"slider-thumb-color": ["#444", "#bbb"],
};
import { RangeSlider } from "/web-components/range-slider.js";

export class Form extends SimpleElement {
static styles = `
${themeColorCSS(colors)}
input[type="range"] {
--slider-track-width: 10em;
--slider-track-height: 0.3em;
--slider-track-color: #0008;
--slider-track-border-radius: 0px;
--slider-thumb-width: 15px;
--slider-thumb-height: 10px;
--slider-thumb-border-radius: 8px;
}
input[type="range"] {
height: var(--slider-track-height);
-webkit-appearance: none;
margin: 5px 10px;
width: var(--slider-track-width);
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-webkit-slider-runnable-track {
width: var(--slider-track-width);
height: var(--slider-track-height);
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: var(--slider-track-color);
border-radius: var(--slider-track-border-radius);
border: 0px solid #000000;
}
input[type="range"]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #000000;
border: 0px solid #000000;
height: var(--slider-thumb-height);
width: var(--slider-thumb-width);
border-radius: var(--slider-thumb-border-radius);
background: var(--slider-thumb-color);
cursor: pointer;
-webkit-appearance: none;
margin-top: -3px;
}
input[type="range"]:focus::-webkit-slider-runnable-track {
background: var(--slider-track-color);
}
input[type="range"]::-moz-range-track {
/* width: var(--slider-track-width); */
height: var(--slider-track-height);
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: var(--slider-track-color);
border-radius: var(--slider-track-border-radius);
border: 0px solid #000000;
}
input[type="range"]::-moz-range-thumb {
box-shadow: 0px 0px 0px #000000;
border: 0px solid #000000;
height: var(--slider-thumb-height);
width: var(--slider-thumb-width);
border-radius: var(--slider-thumb-border-radius);
background: var(--slider-thumb-color);
cursor: pointer;
}
input[type="range"]::-ms-track {
width: var(--slider-track-width);
height: var(--slider-track-height);
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type="range"]::-ms-fill-lower {
background: var(--slider-track-color);
border: 0px solid #000000;
border-radius: var(--slider-thumb-border-radius);
box-shadow: 0px 0px 0px #000000;
}
input[type="range"]::-ms-fill-upper {
background: var(--slider-track-color);
border: 0px solid #000000;
border-radius: var(--slider-thumb-border-radius);
box-shadow: 0px 0px 0px #000000;
}
input[type="range"]::-ms-thumb {
margin-top: 1px;
box-shadow: 0px 0px 0px #000000;
border: 0px solid #000000;
height: var(--slider-thumb-height);
width: var(--slider-thumb-width);
border-radius: var(--slider-thumb-border-radius);
background: var(--slider-thumb-color);
cursor: pointer;
}
input[type="range"]:focus::-ms-fill-lower {
background: var(--slider-track-color);
}
input[type="range"]:focus::-ms-fill-upper {
background: var(--slider-track-color);
}
.ui-form {
display: grid;
grid-template-columns: 32% 68%;
grid-template-columns: 32% auto;
box-sizing: border-box;
gap: 0.35rem 0.35rem;
overflow-x: hidden;
overflow-y: auto;
margin: 0em;
padding: 0em;
}
.ui-form-label {
Expand All @@ -149,20 +40,28 @@ export class Form extends SimpleElement {
text-align: left;
}
.ui-form-value input {
input {
box-sizing: border-box;
background-color: red;
background-color: var(--text-input-background-color);
color: var(--text-input-foreground-color);
border-radius: 0.25em;
border: none;
outline: none;
padding: 0.1em 0.3em;
font-family: "fontra-ui-regular";
border: solid 1px var(--ui-form-input-border-color);
background-color: var(--ui-form-input-background-color);
color: var(--ui-form-input-foreground-color);
width: 9.5em;
}
.ui-form-value input[type="number"] {
width: 4em;
.ui-form-value {
box-sizing: border-box;
}
.ui-form-value input {
width: min(100%, 9.5em);
}
.ui-form-value input[type="range"] {
width: 7em;
.ui-form-value input[type="number"] {
width: 4em;
}
.ui-form-value.text {
Expand Down Expand Up @@ -256,69 +155,38 @@ export class Form extends SimpleElement {
}

_addEditNumberSlider(valueElement, fieldItem) {
const inputElement = document.createElement("input");
const sliderElement = document.createElement("input");
inputElement.type = "number";
sliderElement.type = "range";
for (const el of [inputElement, sliderElement]) {
el.step = "any";
el.min = fieldItem.minValue;
el.max = fieldItem.maxValue;
el.value = fieldItem.value;
el.disabled = fieldItem.disabled;
}
const rangeElement = new RangeSlider();
rangeElement.minValue = fieldItem.minValue;
rangeElement.value = fieldItem.value;
rangeElement.maxValue = fieldItem.maxValue;

{
// Slider change closure
let valueStream = undefined;
let savedCanvasElement;
sliderElement.oninput = (event) => {
// Continuous changes
inputElement.value = round(sliderElement.value, 3);
const value = parseFloat(inputElement.value);
if (!valueStream) {

rangeElement.onChangeCallback = (event) => {
const value = event.value;
if (event.dragBegin) {
valueStream = new QueueIterator(5, true);
this._fieldChanging(fieldItem.key, value, valueStream);
}
valueStream.put(value);
this._dispatchEvent("doChange", { key: fieldItem.key, value: value });
};
sliderElement.onchange = (event) => {
// Single change, or final change after continuous changes

if (valueStream) {
valueStream.put(value);
this._dispatchEvent("doChange", { key: fieldItem.key, value: value });
} else {
this._fieldChanging(fieldItem.key, value, undefined);
}

if (event.dragEnd) {
valueStream.done();
valueStream = undefined;
this._dispatchEvent("endChange", { key: fieldItem.key });
}
};
sliderElement.onmousedown = (event) => {
const activeElement = document.activeElement;
savedCanvasElement =
activeElement?.id === "edit-canvas" ? activeElement : undefined;
};
sliderElement.onmouseup = (event) => {
// sliderElement.onchange is ONLY triggered when the final slider value
// is different from the initial value. However, we may have been in
// a live drag, and we need to handle the end of the slider drag no
// matter what the final value. To work around this, we also listen to
// "mouseup".
sliderElement.onchange(event);
savedCanvasElement?.focus();
};
}

inputElement.onchange = (event) => {
sliderElement.value = inputElement.value;
inputElement.value = sliderElement.value; // Use slider's clamping
this._fieldChanging(fieldItem.key, parseFloat(inputElement.value), undefined);
};
this._fieldGetters[fieldItem.key] = () => sliderElement.value;
this._fieldSetters[fieldItem.key] = (value) => {
inputElement.value = value;
sliderElement.value = value;
};
valueElement.appendChild(inputElement);
valueElement.appendChild(sliderElement);
valueElement.appendChild(rangeElement);
}

addEventListener(eventName, handler, options) {
Expand Down

0 comments on commit e0cac56

Please sign in to comment.