color-elements 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -11
- package/_build/copy-config.js +11 -1
- package/_build/copy-config.json +1 -1
- package/_build/eleventy.js +21 -0
- package/_build/filters-extra.js +3 -0
- package/_data/components.json +8 -0
- package/_includes/component.njk +61 -0
- package/_includes/partials/_nav-links.njk +12 -0
- package/_redirects +1 -1
- package/assets/js/index.js +8 -7
- package/eslint.config.js +316 -0
- package/index.js +6 -4
- package/logo.svg +22 -44
- package/package.json +11 -5
- package/src/channel-slider/README.md +123 -0
- package/src/channel-slider/channel-slider.css +19 -0
- package/src/channel-slider/channel-slider.js +252 -0
- package/{color-gamut → src/color-gamut}/README.md +1 -1
- package/{color-gamut → src/color-gamut}/color-gamut.js +1 -1
- package/src/color-inline/README.md +31 -0
- package/{color-swatch/color-swatch.js → src/color-inline/color-inline.js} +6 -6
- package/src/color-inline/style.css +14 -0
- package/src/color-picker/README.md +48 -0
- package/src/color-picker/color-picker.css +20 -0
- package/src/color-picker/color-picker.js +164 -0
- package/src/color-slider/README.md +193 -0
- package/src/color-slider/color-slider.css +164 -0
- package/src/color-slider/color-slider.js +278 -0
- package/src/color-swatch/README.md +100 -0
- package/src/color-swatch/color-swatch.css +95 -0
- package/{css-color/css-color.js → src/color-swatch/color-swatch.js} +30 -8
- package/src/common/color.js +12 -0
- package/src/common/dom.js +61 -0
- package/src/common/util.js +142 -0
- package/src/index.js.njk +7 -0
- package/src/src.json +3 -0
- package/_data/eleventyComputed.11tydata.js +0 -29
- package/color-slider/README.md +0 -84
- package/color-slider/color-slider.js +0 -79
- package/color-slider/style.css +0 -65
- package/color-swatch/index.njk +0 -40
- package/common/attributes.js +0 -68
- package/common/color.js +0 -10
- package/css-color/index.njk +0 -43
- package/css-color/style.css +0 -67
- /package/{color-gamut/style.css → src/color-gamut/color-gamut.css} +0 -0
- /package/{color-swatch/color-swatch.css → src/color-inline/color-inline.css} +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import "../channel-slider/channel-slider.js";
|
|
2
|
+
import "../color-swatch/color-swatch.js";
|
|
3
|
+
import NudeElement from "../../node_modules/nude-element/src/Element.js";
|
|
4
|
+
import * as dom from "../common/dom.js";
|
|
5
|
+
import Color from "../common/color.js";
|
|
6
|
+
|
|
7
|
+
const Self = class ColorPicker extends NudeElement {
|
|
8
|
+
static tagName = "color-picker";
|
|
9
|
+
|
|
10
|
+
constructor () {
|
|
11
|
+
super();
|
|
12
|
+
|
|
13
|
+
this.attachShadow({mode: "open"});
|
|
14
|
+
let styleURL = new URL(`./${Self.tagName}.css`, import.meta.url);
|
|
15
|
+
this.shadowRoot.innerHTML = `
|
|
16
|
+
<style>@import url("${ styleURL }")</style>
|
|
17
|
+
<div id=sliders></div>
|
|
18
|
+
<slot name="swatch">
|
|
19
|
+
<color-swatch size="large" id="swatch">
|
|
20
|
+
<slot slot="swatch-content"></slot>
|
|
21
|
+
<input value="oklch(70% 0.25 138)" id="color" />
|
|
22
|
+
</color-swatch>
|
|
23
|
+
</slot>
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
this._el = dom.named(this);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
connectedCallback() {
|
|
30
|
+
super.connectedCallback?.();
|
|
31
|
+
this._el.sliders.addEventListener("input", this);
|
|
32
|
+
this._el.swatch.addEventListener("input", this);
|
|
33
|
+
|
|
34
|
+
this.render();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
disconnectedCallback() {
|
|
38
|
+
this._el.sliders.removeEventListener("input", this);
|
|
39
|
+
this._el.swatch.removeEventListener("input", this);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
handleEvent(event) {
|
|
43
|
+
this.render(event.target);
|
|
44
|
+
|
|
45
|
+
this.dispatchEvent(new event.constructor(event.type, {...event}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
render (source) {
|
|
49
|
+
if (!source || this._el.sliders.contains(source)) {
|
|
50
|
+
// From sliders
|
|
51
|
+
let coords = [...this._el.sliders.children].map(el => el.value);
|
|
52
|
+
this.color = new Color(this.space, coords);
|
|
53
|
+
this._el.swatch.value = this.color;
|
|
54
|
+
}
|
|
55
|
+
else if (!source || this._el.swatch.contains(source)) {
|
|
56
|
+
// From swatch
|
|
57
|
+
if (!this._el.swatch.color) {
|
|
58
|
+
// Invalid color, or still typing
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.color = this._el.swatch.color;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (let slider of this._el.sliders.children) {
|
|
65
|
+
slider.defaultColor = this.color;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
propChangedCallback ({name, prop, detail: change}) {
|
|
70
|
+
if (name === "space") {
|
|
71
|
+
let i = 0;
|
|
72
|
+
for (let channel in this.space.coords) {
|
|
73
|
+
let slider = this._el.sliders.children[i++];
|
|
74
|
+
|
|
75
|
+
if (slider) {
|
|
76
|
+
slider.space = this.space;
|
|
77
|
+
slider.channel = channel;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this._el.sliders.insertAdjacentHTML("beforeend", `<channel-slider space="${ this.space.id }" channel="${ channel }"></channel-slider>`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (name === "color") {
|
|
86
|
+
for (let slider of this._el.sliders.children) {
|
|
87
|
+
slider.color = this.color;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (this.color && (!this._el.swatch.color || !this.color.equals(this._el.swatch.color))) {
|
|
91
|
+
// Avoid typing e.g. "red" and having it replaced with "rgb(100% 0% 0%)" under your caret
|
|
92
|
+
prop.applyChange(this._el.swatch, change);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static props = {
|
|
98
|
+
space: {
|
|
99
|
+
default: "oklch",
|
|
100
|
+
parse (value) {
|
|
101
|
+
if (value instanceof Color.Space || value === null || value === undefined) {
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
value += "";
|
|
106
|
+
|
|
107
|
+
return Color.Space.get(value);
|
|
108
|
+
},
|
|
109
|
+
stringify (value) {
|
|
110
|
+
return value?.id;
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
defaultColor: {
|
|
115
|
+
type: Color,
|
|
116
|
+
convert (color) {
|
|
117
|
+
return color.to(this.space);
|
|
118
|
+
},
|
|
119
|
+
default () {
|
|
120
|
+
let coords = [];
|
|
121
|
+
for (let channel in this.space.coords) {
|
|
122
|
+
let spec = this.space.coords[channel];
|
|
123
|
+
let range = spec.refRange ?? spec.range;
|
|
124
|
+
coords.push((range[0] + range[1]) / 2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return new Color(this.space, coords);
|
|
128
|
+
},
|
|
129
|
+
reflect: {
|
|
130
|
+
from: "color",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
color: {
|
|
135
|
+
type: Color,
|
|
136
|
+
set (value) {
|
|
137
|
+
this.defaultColor = new Color(value).to(this.space);
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
static events = {
|
|
143
|
+
change: {
|
|
144
|
+
from () {
|
|
145
|
+
return [this._el.sliders, this._el.swatch];
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
input: {
|
|
149
|
+
from () {
|
|
150
|
+
return [this._el.sliders, this._el.swatch];
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
valuechange: {
|
|
154
|
+
propchange: "value",
|
|
155
|
+
},
|
|
156
|
+
colorchange: {
|
|
157
|
+
propchange: "color",
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
customElements.define(Self.tagName, Self);
|
|
163
|
+
|
|
164
|
+
export default Self;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# `<color-slider>`
|
|
2
|
+
|
|
3
|
+
Creates a slider with a gradient background, primarily intended for color picking.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
There are many ways to use this component, depending on what you need.
|
|
8
|
+
E.g. if all you need is styling sliders with arbitrary gradients you don’t even need a component,
|
|
9
|
+
you can just [use the CSS file](#css-only) and a few classes and CSS variables to style regular HTML sliders.
|
|
10
|
+
|
|
11
|
+
The actual component does a lot more:
|
|
12
|
+
- It provides a `color` property with the actual color value
|
|
13
|
+
- It takes care of even displaying colors in unsupported color spaces
|
|
14
|
+
- Editable tooltip showing the current value or progress _(optional)_
|
|
15
|
+
- Convenient events like `colorchange` and `valuechange` that fire even when the value changes programmatically
|
|
16
|
+
|
|
17
|
+
Basic example:
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<color-slider space="hsl"
|
|
21
|
+
stops="oklch(90% 50% 100), darkcyan, indigo"></color-slider>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
You can listen to the `colorchange` event and grab the `color` property to get the current color value:
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<color-slider space="hsl"
|
|
28
|
+
stops="red, yellow, lime, aqua, blue, magenta, red"
|
|
29
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
30
|
+
<output></output>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
In fact, you can combine it with a [`<color-inline>`](../color-inline/) or [`<color-swatch>`](../color-swatch/) element to display the color in a more visual way:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<color-slider space="oklch"
|
|
37
|
+
stops="oklch(80% 50% 70), oklch(65% 50% 180)"
|
|
38
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
39
|
+
<color-inline></color-inline>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Colors and color spaces not supported by the browser also work:
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<color-slider space="okhsl" stops="gold, color(--okhsl 180 100% 50%)"></color-slider>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
You can set the `value` attribute to specify an initial color other than the midpoint:
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<color-slider space="oklch"
|
|
52
|
+
stops="oklch(85% 50% 80), oklch(65% 50% 180)"
|
|
53
|
+
value="0.1"
|
|
54
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
55
|
+
<color-inline></color-inline>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
You can use a different min and max value and it’s just linearly mapped to the stops:
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<color-slider space="oklch"
|
|
62
|
+
stops="oklch(85% 50% 80), oklch(65% 50% 180)"
|
|
63
|
+
min="-50" max="50" value="20"
|
|
64
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
65
|
+
<color-inline></color-inline>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
You can add an editable tooltip by simply using the `tooltip` attribute:
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<color-slider space="oklch"
|
|
72
|
+
stops="oklch(85% 50% 80), oklch(65% 50% 180)"
|
|
73
|
+
min="-50" max="50" value="20"
|
|
74
|
+
tooltip
|
|
75
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
76
|
+
<color-inline></color-inline>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
By default, the tooltip will show the slider value as a number.
|
|
80
|
+
If you want to show the progress instead, you can specify `"progress"` as the attribute value:
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<color-slider space="oklch"
|
|
84
|
+
stops="oklch(85% 50% 80), oklch(65% 50% 180)"
|
|
85
|
+
min="-50" max="50" value="20"
|
|
86
|
+
tooltip="progress"
|
|
87
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
88
|
+
<color-inline></color-inline>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
All properties are reactive and can be set programmatically:
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<button onclick="this.nextElementSibling.value = Math.random()">Random color</button>
|
|
95
|
+
<color-slider space="oklch"
|
|
96
|
+
stops="gold, darkcyan, indigo"
|
|
97
|
+
oncolorchange="this.nextElementSibling.textContent = this.color"></color-slider>
|
|
98
|
+
<color-swatch></color-swatch>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
You can style it to look quite different:
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<style>
|
|
105
|
+
.lr-slider {
|
|
106
|
+
--slider-height: .3em;
|
|
107
|
+
--slider-thumb-width: 1em;
|
|
108
|
+
--slider-thumb-height: 1em;
|
|
109
|
+
--slider-thumb-radius: 1em;
|
|
110
|
+
--slider-thumb-border: 3px solid oklab(50% 0 0);
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
113
|
+
<color-slider class="lr-slider" space="oklch"
|
|
114
|
+
stops="yellowgreen, gold, red"></color-slider>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### CSS-only usage
|
|
119
|
+
|
|
120
|
+
If you just want the styling of `<color-slider>` and not any of the API (or are fine dealing with the lower level details on your own),
|
|
121
|
+
you *can* just use the CSS file:
|
|
122
|
+
|
|
123
|
+
```css
|
|
124
|
+
@import url("https://elements.colorjs.io/src/color-slider/color-slider.css");
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This is perfect for when the gradient is more of a visual aid than a functional part of your UI,
|
|
128
|
+
e.g. when picking a temperature:
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<style>
|
|
132
|
+
@import url("color-slider.css");
|
|
133
|
+
</style>
|
|
134
|
+
<label>
|
|
135
|
+
Temperature:
|
|
136
|
+
<input type="range" class="color-slider" min="-20" max="50" value="15"
|
|
137
|
+
style="--slider-color-stops: oklch(65% 0.1 250), yellowgreen, gold, orange, red, darkred" />
|
|
138
|
+
</label>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Then use a `color-slider` class on your slider element, and use [CSS variables](#css-variables) to set the gradient (either directly via `--slider-gradient` or generated via `--slider-color-stops` + `--color-space`).
|
|
142
|
+
|
|
143
|
+
## Reference
|
|
144
|
+
|
|
145
|
+
### Attributes & Properties
|
|
146
|
+
|
|
147
|
+
| Attribute | Property | Property type | Default value | Description |
|
|
148
|
+
|-----------|----------|---------------|---------------|-------------|
|
|
149
|
+
| `space` | `space` | `ColorSpace` | `string` | `oklch` | The color space to use for interpolation. |
|
|
150
|
+
| `color` | `color` | `Color` | `string` | `oklch(50 50% 180)` | The current color value. |
|
|
151
|
+
| `stops` | `stops` | `String` | `Array<Color>` | - | Comma-separated list of color stops |
|
|
152
|
+
| `min` | `min` | `number` | 0 | The minimum value for the slider. |
|
|
153
|
+
| `max` | `max` | `number` | 1 | The maximum value for the slider. |
|
|
154
|
+
| `step` | `step` | `number` | Computed automatically based on `this.min` and `this.max`. | The granularity that the slider's current value must adhere to. |
|
|
155
|
+
| `value` | `value` | `number` | `(this.min + this.max) / 2` | The current value of the slider. |
|
|
156
|
+
|
|
157
|
+
### CSS variables
|
|
158
|
+
|
|
159
|
+
If you’re using the component, these are mostly set automatically.
|
|
160
|
+
If you’re only using the CSS file, you should set these yourself.
|
|
161
|
+
|
|
162
|
+
| Variable | Type | Description |
|
|
163
|
+
|----------|---------------|-------------|
|
|
164
|
+
| `--slider-color-stops` | `<color>#` | Comma-separated list of color stops. |
|
|
165
|
+
| `--color-space` | `<ident>` | The color space to use for interpolation. |
|
|
166
|
+
| `--hue-interpolation` | `[shorter` | `longer` | `increasing` | `decreasing] hue` | The color space to use for interpolation. |
|
|
167
|
+
| `--slider-gradient` | `<image>` | The gradient to use as the background. |
|
|
168
|
+
| `--slider-height` | `<length>` | Height of the slider track. |
|
|
169
|
+
| `--slider-thumb-width` | `<length>` | Width of the slider thumb. |
|
|
170
|
+
| `--slider-thumb-height` | `<length>` | Height of the slider thumb. |
|
|
171
|
+
| `--slider-thumb-height-offset` | `<length>` | Offset the thumb height from the track height. |
|
|
172
|
+
| `--slider-thumb-radius` | `<length>` | Radius of the slider thumb. |
|
|
173
|
+
| `--slider-thumb-background` | `<color>` | Background color of the slider thumb. |
|
|
174
|
+
| `--slider-thumb-border` | `<line-width>` || `<line-style>` || `<color>` | Border of the slider thumb. |
|
|
175
|
+
| `--slider-thumb-border-active` | `<line-width>` || `<line-style>` || `<color>` | Border of the slider thumb in active state. |
|
|
176
|
+
| `--slider-thumb-scale-active` | `<number>` | Scale transform applied to the slider thumb in active state. |
|
|
177
|
+
| `--tooltip-background` | `<color>` | Background color of the tooltip. |
|
|
178
|
+
| `--tooltip-border-radius` | `<length>` | Border radius of the tooltip. |
|
|
179
|
+
| `--tooltip-pointer-height` | `<length>` | Height of the tooltip pointer triangle. |
|
|
180
|
+
| `--tooltip-pointer-angle` | `<angle>` | Angle of the tooltip pointer triangle. |
|
|
181
|
+
|
|
182
|
+
### Events
|
|
183
|
+
|
|
184
|
+
| Name | Description |
|
|
185
|
+
|------|-------------|
|
|
186
|
+
| `input` | Fired when the color changes due to user action. |
|
|
187
|
+
| `change` | Fired when the color changes due to user action. |
|
|
188
|
+
| `valuechange` | Fired when the value changes for any reason, and once during initialization. |
|
|
189
|
+
| `colorchange` | Fired when the color changes for any reason, and once during initialization. |
|
|
190
|
+
|
|
191
|
+
## Planned features
|
|
192
|
+
|
|
193
|
+
- Discrete scales & steps
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: flex;
|
|
3
|
+
position: relative;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.color-slider,
|
|
7
|
+
.slider-tooltip {
|
|
8
|
+
--transparency: repeating-conic-gradient(transparent 0 25%, rgb(0 0 0 / .05) 0 50%) 0 0 / 1.5em 1.5em content-box border-box;
|
|
9
|
+
|
|
10
|
+
--_slider-color-stops: var(--slider-color-stops, transparent 0% 100%);
|
|
11
|
+
--_slider-gradient: var(--slider-gradient, linear-gradient(to right var(--in-space, ), var(--_slider-color-stops)));
|
|
12
|
+
--_slider-height: var(--slider-height, 2.2em);
|
|
13
|
+
|
|
14
|
+
--_slider-thumb-width: var(--slider-thumb-width, 1em);
|
|
15
|
+
--_slider-thumb-height-offset: var(--slider-thumb-height-offset, 2px);
|
|
16
|
+
--_slider-thumb-height: var(--slider-thumb-height, calc(var(--_slider-height) + var(--_slider-thumb-height-offset)));
|
|
17
|
+
--_slider-thumb-radius: var(--slider-thumb-radius, .16em);
|
|
18
|
+
--_slider-thumb-background: var(--slider-thumb-background, var(--color, transparent));
|
|
19
|
+
--_slider-thumb-border: var(--slider-thumb-border, 1px solid oklab(.2 0 0));
|
|
20
|
+
--_slider-thumb-border-active: var(--slider-thumb-border-active, 2px solid oklab(.4 0 0));
|
|
21
|
+
--_slider-thumb-scale-active: var(--slider-thumb-scale-active, 1.1);
|
|
22
|
+
|
|
23
|
+
--_tooltip-background: var(--tooltip-background, hsl(0 0 0 / 80%));
|
|
24
|
+
--_tooltip-border-radius: var(--tooltip-border-radius, .3em);
|
|
25
|
+
--_tooltip-pointer-height: var(--tooltip-pointer-height, .3em);
|
|
26
|
+
--_tooltip-pointer-angle: var(--tooltip-pointer-angle, 90deg);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.color-slider {
|
|
30
|
+
@supports (background: linear-gradient(in oklab, red, tan)) {
|
|
31
|
+
--in-space: in var(--color-space, oklab) var(--hue-interpolation, );
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
display: block;
|
|
35
|
+
margin: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
-moz-appearance: none;
|
|
38
|
+
-webkit-appearance: none;
|
|
39
|
+
background: var(--_slider-gradient), var(--transparency);
|
|
40
|
+
background-origin: border-box;
|
|
41
|
+
background-clip: border-box;
|
|
42
|
+
height: var(--_slider-height);
|
|
43
|
+
border-radius: .3em;
|
|
44
|
+
border: 1px solid rgb(0 0 0 / 8%);
|
|
45
|
+
|
|
46
|
+
&::-webkit-slider-thumb {
|
|
47
|
+
-webkit-appearance: none;
|
|
48
|
+
box-sizing: content-box;
|
|
49
|
+
width: var(--_slider-thumb-width);
|
|
50
|
+
height: var(--_slider-thumb-height);
|
|
51
|
+
border-radius: var(--_slider-thumb-radius);
|
|
52
|
+
border: var(--_slider-thumb-border);
|
|
53
|
+
box-shadow: 0 0 0 1px white;
|
|
54
|
+
background: var(--color, transparent);
|
|
55
|
+
transition: 200ms, 0s background;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&::-moz-range-thumb {
|
|
59
|
+
box-sizing: content-box;
|
|
60
|
+
width: var(--_slider-thumb-width);
|
|
61
|
+
height: var(--_slider-thumb-height);
|
|
62
|
+
border-radius: var(--_slider-thumb-radius);
|
|
63
|
+
border: var(--_slider-thumb-border);
|
|
64
|
+
box-shadow: 0 0 0 1px white;
|
|
65
|
+
background: var(--color, transparent);
|
|
66
|
+
transition: 200ms, 0s background;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&::-webkit-slider-thumb:active {
|
|
70
|
+
border: var(--_slider-thumb-border-active);
|
|
71
|
+
scale: var(--_slider-thumb-scale-active);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&::-moz-range-thumb:active {
|
|
75
|
+
border: var(--_slider-thumb-border-active);
|
|
76
|
+
scale: var(--_slider-thumb-scale-active);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&::-moz-range-track {
|
|
80
|
+
background: none;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.slider-tooltip {
|
|
85
|
+
position: absolute;
|
|
86
|
+
left: clamp(-20%,
|
|
87
|
+
100% * var(--progress)
|
|
88
|
+
- (var(--progress) - 0.5) * var(--_slider-thumb-width) / 2 /* center on slider thumb */
|
|
89
|
+
, 100%);
|
|
90
|
+
bottom: calc(100% + 3px);
|
|
91
|
+
translate: -50%;
|
|
92
|
+
transform-origin: bottom;
|
|
93
|
+
display: flex;
|
|
94
|
+
padding-block: .3em;
|
|
95
|
+
padding-inline: .4em;
|
|
96
|
+
border: var(--_tooltip-pointer-height) solid transparent;
|
|
97
|
+
border-radius: calc(var(--_tooltip-border-radius) + var(--_tooltip-pointer-height));
|
|
98
|
+
text-align: center;
|
|
99
|
+
color: white;
|
|
100
|
+
background:
|
|
101
|
+
conic-gradient(from calc(-1 * var(--_tooltip-pointer-angle) / 2) at bottom, var(--_tooltip-background) var(--_tooltip-pointer-angle), transparent 0) border-box bottom / 100% var(--_tooltip-pointer-height) no-repeat,
|
|
102
|
+
var(--_tooltip-background) padding-box;
|
|
103
|
+
color-scheme: dark;
|
|
104
|
+
transition:
|
|
105
|
+
visibility 0s 200ms,
|
|
106
|
+
opacity 200ms,
|
|
107
|
+
scale 200ms,
|
|
108
|
+
width 100ms,
|
|
109
|
+
left 200ms cubic-bezier(.17,.67,.49,1.48);
|
|
110
|
+
|
|
111
|
+
&::after {
|
|
112
|
+
content: var(--tooltip-suffix);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
input {
|
|
116
|
+
all: unset;
|
|
117
|
+
|
|
118
|
+
&:where([type=number]) {
|
|
119
|
+
--content-width: calc(var(--value-length) * 1ch);
|
|
120
|
+
width: calc(var(--content-width, 2ch) + 1.2em);
|
|
121
|
+
min-width: calc(2ch + 1.2em);
|
|
122
|
+
box-sizing: content-box;
|
|
123
|
+
|
|
124
|
+
&::-webkit-textfield-decoration-container {
|
|
125
|
+
gap: .2em;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@container style(--tooltip-suffix) {
|
|
129
|
+
&::-webkit-textfield-decoration-container {
|
|
130
|
+
flex-flow: row-reverse;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Don’t auto hide the spin buttons */
|
|
135
|
+
&::-webkit-inner-spin-button {
|
|
136
|
+
opacity: 1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@supports (field-sizing: content) {
|
|
141
|
+
field-sizing: content;
|
|
142
|
+
width: auto;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Prevent input from moving all over the place as we type */
|
|
146
|
+
&:focus {
|
|
147
|
+
transition-delay: .5s;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
&:not(:is(:focus-within, :hover) > *, .color-slider:is(:focus, :hover) + *, :focus, :hover) {
|
|
152
|
+
visibility: hidden;
|
|
153
|
+
opacity: 0;
|
|
154
|
+
scale: .5;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
:host(:not([tooltip])) .slider-tooltip {
|
|
159
|
+
display: none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
:host([tooltip="progress"]) .slider-tooltip {
|
|
163
|
+
--tooltip-suffix: "%";
|
|
164
|
+
}
|