-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New WC] Color space dropdown #123
Comments
Name brainstorming:
Wrt specifying the spaces:
The component should do double duty and function as a label for the color space, with clear affordances for clicking to change it. An MVP would be to just use a |
By analogy with I already have a working MVP, so if we have a name, it would help. |
I came up with this MVP (I use import ColorElement from "../common/color-element.js";
const Self = class SpacePicker extends ColorElement {
static tagName = "space-picker";
static url = import.meta.url;
static shadowStyle = true;
static shadowTemplate = `<select id="picker" part="picker"></select>`;
constructor () {
super();
this._el = {};
this._el.picker = this.shadowRoot.querySelector("#picker");
}
connectedCallback () {
super.connectedCallback?.();
this._el.picker.addEventListener("change", this);
}
disconnectedCallback () {
super.disconnectedCallback?.();
this._el.picker.removeEventListener("change", this);
}
handleEvent (event) {
if (event.type === "change" && event.target === this._el.picker) {
this.value = this._el.picker.value;
}
this.dispatchEvent(new event.constructor(event.type, {...event}));
}
propChangedCallback ({name, prop, detail: change}) {
if (name === "spaces") {
this._el.picker.innerHTML = Object.entries(this.spaces)
.map(([id, space]) => `<option value="${id}">${space.name}</option>`)
.join("\n");
}
if (name === "value" || name === "spaces") {
if (this.value?.id !== this._el.picker.value) {
if (this.value.id in this.spaces) {
this._el.picker.value = this.value.id;
}
else {
let currentValue = this.spaces[this._el.picker.value];
console.warn(`No color space with id = “${ this.value.id }” was found among the specified ones. Using the current one (${ currentValue.id }) instead.`);
this.value = currentValue;
}
}
}
}
static props = {
value: {
default () {
return Self.Color.Space.get(this._el.picker.value);
},
parse (value) {
if (value instanceof Self.Color.Space || value === null || value === undefined) {
return value;
}
value += "";
return Self.Color.Space.get(value);
},
stringify (value) {
return value?.id;
},
},
spaces: {
type: {
is: Object,
get values () {
return Self.Color.Space;
},
defaultValue: (id, index) => {
try {
return Self.Color.Space.get(id);
}
catch (e) {
console.error(e);
}
},
},
default: () => Self.Color.spaces,
convert (value) {
// Drop non-existing spaces
return Object.fromEntries(Object.entries(value).filter(([id, space]) => space));
},
stringify (value) {
return Object.entries(value).map(([id, space]) => id).join(", ");
},
},
};
static events = {
change: {
from () {
return this._el.picker;
},
},
spacechange: {
propchange: "value",
},
};
static formAssociated = {
like: el => el._el.picker,
role: "combobox",
valueProp: "value",
changeEvent: "spacechange",
};
};
Self.define();
export default Self; #picker {
font: inherit;
color: inherit;
background: inherit;
field-sizing: content;
cursor: pointer;
} |
The |
Nah, it shouldn't. Having an object is more convenient and is aligned with the |
Here is a sneak peek of how it works: Color.Space.Picker.mp4I will send a PR once we decide on the component's name so we can iterate. |
I think This is fine for an MVP, but eventually I would like to also support some common groupings too, e.g. to show polar & rectangular color spaces in separate |
I was thinking of grouping, too (I examined what you did in your Color Palettes research), but I couldn't think of a default one, so I decided to let it go for now.
I want to make sure I get it right: the name of the prop is |
No lol, what would that mean? What I meant was, the prop would only exist in JS, i.e. it would not reflect. The prop name would probably be something like |
I thought so, but had to make sure 😂 |
MVP is alive and available for experiments: https://elements.colorjs.io/src/space-picker/ |
I have two types of working homemade examples here: https://sidewayss.github.io/rAF/apps/color/ The two lists in the form are identical, the one on the right is a clone of the one on the left. The version inside the If you look at the code that loads the options into the lists:
The ability to include custom spaces depends on the timing of populating the list, especially if you want to sort the list. Also note that in the two primary lists, the re names: maybe |
I think it's a reasonable request. I also think To make custom things possible, I'd suggest adding a new JS-only prop to handle it, such as It can be used, for example, like so: <space-picker id="picker" spaces="oklch, p3, srgb" value="oklch"></space-picker>
<script>
picker.labelFor = space => space.id;
</script> As a result, we'll get: Instead of the default: Internally, this prop can be defined like so: labelFor: {
type: {
is: Function,
arguments: ["space"],
},
reflect: false,
},
We can also do this, if there are use cases, the same way we can provide custom labels. E.g., via a @LeaVerou, what do you think? |
@DmitrySharabin - I understand your
|
I'm not sure wanting to display a CSS id is a common enough use case to warrant special syntax — I'd be inclined to go with what Dmitry suggested, and just called it Regarding things like |
Not just displaying, putting in the option's value, though maybe that should be outside the scope because it's about using CSS instead of Color.js. In other words, I don't disagree. The whole thing would be moot if Color.js space ids aligned with CSS :-)
I now see that in the demo. I was also hoping that maybe @DmitrySharabin could explain how his proposals would handle these cases, or not. I didn't understand his initial proposal for |
OK, I now see that |
Yeah, this is out of scope. The picker gives you a
The |
Wow, I've never seen it used, though I'm no expert. I don't see it being used in the demo page here either. I see |
Yup, at this point its convention to use the text content as the label. But in theory, it would be totally fine to do this: |
So you're saying that the Will this new element be used outside of any relationship with a
That is what I thought. Yea, I read the MDN docs for |
This component automatically gets populated with all color spaces (or a subset, e.g., polar or perceptually uniform, or even a custom subset).
<color-chart>
,<color-scale>
, and<color-picker>
can benefit from it by integrating it and providing an easy way to choose (and dynamically change) the color space. Right now, it requires a lot of plumbing.The text was updated successfully, but these errors were encountered: