chore: knob upd & memories

This commit is contained in:
2026-06-02 18:10:19 +03:00
parent 3da99a7214
commit b6017d60c8
6 changed files with 544 additions and 0 deletions
+198
View File
@@ -738,6 +738,204 @@ textarea.modern-sk-field {
white-space: nowrap;
}
/* ---------- KNOB (circular slider) ----------
Skeuomorphic rotary control. The dial follows the pointer 1:1 while dragging
(bound to the mouse); the gauge fill + value snap to detents and *glide*
between them (like the stepped Slider) when `--animated`. Anatomy:
recessed SVG gauge ring → glossy cap → knurled dial (rotates, carries the
accent pointer) → turned-metal hub. Sizing flows from --knob-size. */
.modern-sk-knob {
--knob-size: 108px;
--knob-accent: var(--lime);
--knob-accent-deep: var(--lime-deep);
--knob-glow: rgba(190, 242, 100, 0.5);
position: relative;
flex-shrink: 0;
width: var(--knob-size);
height: var(--knob-size);
cursor: grab;
outline: none;
touch-action: none;
-webkit-tap-highlight-color: transparent;
}
.modern-sk-knob.is-dragging {
cursor: grabbing;
}
.modern-sk-knob--disabled {
cursor: default;
opacity: 0.55;
}
/* recessed gauge ring */
.modern-sk-knob__gauge {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
overflow: visible;
pointer-events: none;
}
.modern-sk-knob__track {
fill: none;
stroke: var(--steel-800);
stroke-width: 5;
stroke-linecap: round;
}
/* The fill is the full arc, revealed up to the value via stroke-dashoffset (set
inline as a plain number). When `--animated`, transition the offset so the
accent eases along the circle between detents. */
.modern-sk-knob__fill {
fill: none;
stroke: var(--knob-accent);
stroke-width: 5;
stroke-linecap: round;
filter: drop-shadow(0 0 5px var(--knob-glow));
transition: stroke var(--dur-quick) var(--ease-out);
}
.modern-sk-knob--animated .modern-sk-knob__fill {
transition:
stroke-dashoffset 0.12s ease-out,
stroke var(--dur-quick) var(--ease-out);
}
.modern-sk-knob__tick {
stroke: var(--fg-3);
stroke-width: 1.6;
stroke-linecap: round;
opacity: 0.45;
transition:
stroke var(--dur-quick),
opacity var(--dur-quick);
}
.modern-sk-knob__tick.is-on {
stroke: var(--knob-accent);
opacity: 0.95;
}
/* glossy cap — static top-down gloss (light source stays put) */
.modern-sk-knob__cap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: calc(var(--knob-size) - 34px);
height: calc(var(--knob-size) - 34px);
border-radius: 50%;
border: 1px solid var(--hair-strong);
background:
radial-gradient(circle at 50% 30%, rgba(255, 255, 255, 0.16), transparent 58%),
var(--grad-key);
box-shadow:
0 1px 0 rgba(255, 255, 255, 0.08) inset,
0 4px 9px rgba(0, 0, 0, 0.5),
0 11px 22px rgba(0, 0, 0, 0.42);
overflow: hidden;
transition: box-shadow var(--dur-quick) var(--ease-out);
}
/* knurled dial — rotates with the pointer, carries the glowing pointer dot.
The ribbed grip lives on ::before (masked to a ring) so the pointer dot can
sit unmasked on top and keep its full halo. While dragging it tracks the
mouse with no transition; otherwise it glides to the settled value. */
.modern-sk-knob__dial {
position: absolute;
inset: 0;
border-radius: 50%;
will-change: transform;
}
.modern-sk-knob--animated .modern-sk-knob__dial {
transition: transform 0.12s ease-out;
}
.modern-sk-knob.is-dragging .modern-sk-knob__dial {
transition: none;
}
.modern-sk-knob__dial::before {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
background: repeating-conic-gradient(
from 0deg,
rgba(255, 255, 255, 0.09) 0deg 3deg,
rgba(0, 0, 0, 0.28) 3deg 6deg
);
-webkit-mask: radial-gradient(circle, transparent 0 58%, #000 61% 100%);
mask: radial-gradient(circle, transparent 0 58%, #000 61% 100%);
}
.modern-sk-knob__pointer {
position: absolute;
top: 5%;
left: 50%;
transform: translateX(-50%);
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--knob-accent);
box-shadow: 0 0 6px var(--knob-glow);
}
/* turned-metal hub covers the inner ends; pointer reads as an outer notch */
.modern-sk-knob__hub {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 48%;
height: 48%;
border-radius: 50%;
background: radial-gradient(circle at 50% 34%, #36372c, #1d1e17);
box-shadow:
0 1px 0 rgba(255, 255, 255, 0.07) inset,
0 1px 3px rgba(0, 0, 0, 0.55);
}
.modern-sk-knob:focus-visible .modern-sk-knob__cap {
box-shadow:
var(--focus-ring),
0 1px 0 rgba(255, 255, 255, 0.08) inset,
0 4px 9px rgba(0, 0, 0, 0.5),
0 11px 22px rgba(0, 0, 0, 0.42);
}
/* ember accent variant */
.modern-sk-knob--ember {
--knob-accent: var(--ember);
--knob-accent-deep: var(--ember-deep);
--knob-glow: rgba(233, 87, 43, 0.5);
}
@media (prefers-reduced-motion: reduce) {
.modern-sk-knob--animated .modern-sk-knob__fill,
.modern-sk-knob--animated .modern-sk-knob__dial {
transition: none;
}
}
/* light theme: brighter cap gloss, darker knurl ridges so the grip reads, a
pale turned hub, and a lighter recessed gauge channel. */
[data-theme='light'] .modern-sk-knob__cap {
box-shadow:
0 1px 0 rgba(255, 255, 255, 0.9) inset,
0 2px 5px rgba(0, 0, 0, 0.16),
0 7px 16px rgba(0, 0, 0, 0.12);
}
[data-theme='light'] .modern-sk-knob__dial::before {
background: repeating-conic-gradient(
from 0deg,
rgba(0, 0, 0, 0.09) 0deg 3deg,
rgba(255, 255, 255, 0.6) 3deg 6deg
);
}
[data-theme='light'] .modern-sk-knob__hub {
background: radial-gradient(circle at 50% 34%, #ffffff, #e2e2d6);
box-shadow:
0 1px 0 rgba(255, 255, 255, 0.9) inset,
0 1px 3px rgba(0, 0, 0, 0.16);
}
[data-theme='light'] .modern-sk-knob__track {
stroke: var(--steel-500);
}
[data-theme='light'] .modern-sk-knob__tick {
stroke: var(--steel-400);
}
/* ---------- STEPPER ---------- */
.modern-sk-stepper {
display: inline-flex;