diff --git a/ui/src/components/ParameterField.jsx b/ui/src/components/ParameterField.jsx index 77c79b8..8dfb6c2 100644 --- a/ui/src/components/ParameterField.jsx +++ b/ui/src/components/ParameterField.jsx @@ -1,9 +1,9 @@ import Wheel from "@uiw/react-color-wheel"; import { hsvaToRgba, rgbaToHsva } from "@uiw/color-convert"; -import { Copy, RotateCcw, Zap } from "lucide-react"; +import { RotateCcw, Zap } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; import { useThrottledParameterValue } from "../hooks/useThrottledParameterValue"; -import { ParameterValueDisplay } from "./ParameterValueDisplay"; function valuesMatch(left, right) { return JSON.stringify(left) === JSON.stringify(right); @@ -23,7 +23,7 @@ function ParameterHeader({ layer, parameter, onReset, resetDisabled }) {
- {parameter.description ?

{parameter.description}

: null} + {parameter.description ?

{parameter.description}

: null}
+
+ {["R", "G", "B", "A"].map((label, index) => ( + + ))}
-
- ); } @@ -267,17 +310,18 @@ export function ParameterField({ layer, parameter, onParameterChange }) { return (
{header} - - +
+ +
); } @@ -286,19 +330,20 @@ export function ParameterField({ layer, parameter, onParameterChange }) { return (
{header} - - +
+ +
); } @@ -307,16 +352,17 @@ export function ParameterField({ layer, parameter, onParameterChange }) { return (
{header} - sendValue(event.target.value)} - onBlur={endInteraction} - /> - +
+ sendValue(event.target.value)} + onBlur={endInteraction} + /> +
); } @@ -326,15 +372,16 @@ export function ParameterField({ layer, parameter, onParameterChange }) { return (
{header} - - +
+ +
); } diff --git a/ui/src/styles.css b/ui/src/styles.css index 2cb1a3f..859e8a1 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -701,7 +701,6 @@ pre { .shader-picker__meta, .shader-picker__empty, .parameter__value, -.parameter__alpha, .parameter__osc, .parameter__reset { color: var(--app-muted); @@ -876,21 +875,27 @@ pre { } .parameter-grid { - grid-template-columns: repeat(auto-fit, minmax(17.5rem, 1fr)); - gap: 0.625rem; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 32rem), 1fr)); + gap: 0.5rem; + align-items: start; } .parameter { - padding: 0.75rem; + position: relative; + grid-template-columns: minmax(16rem, 0.9fr) minmax(18rem, 1.35fr); + gap: 0.625rem; + align-items: center; + padding: 0.55rem 0.65rem; border: 1px solid var(--app-border); background: #141a23; } .parameter__header { display: grid; - grid-template-columns: minmax(5.5rem, auto) minmax(0, 1fr) auto; - gap: 0.5rem; - align-items: start; + grid-template-columns: minmax(0, 1fr) auto auto; + gap: 0.35rem; + align-items: center; + min-width: 0; } .parameter__title { @@ -899,23 +904,30 @@ pre { .parameter__title label { display: block; + overflow: hidden; + font-size: 0.9rem; + line-height: 1.2; + text-overflow: ellipsis; + white-space: nowrap; } .parameter__title p { - margin: 0.2rem 0 0; + margin: 0.12rem 0 0; + overflow: hidden; color: var(--app-muted); - font-size: 0.82rem; - line-height: 1.3; + font-size: 0.76rem; + line-height: 1.25; + text-overflow: ellipsis; + white-space: nowrap; } .parameter__osc, .parameter__reset { display: inline-flex; align-items: center; - justify-content: flex-end; - gap: 0.375rem; - width: auto; - min-width: 0; + justify-content: center; + width: 24px; + min-width: 24px; min-height: 24px; padding: 0; border: 0; @@ -923,18 +935,16 @@ pre { font-weight: 500; } -.parameter__reset { - justify-content: center; - width: 24px; - min-width: 24px; - color: var(--app-muted); +.parameter__osc { + width: 34px; + min-width: 34px; + font-size: 0.66rem; + font-weight: 800; + letter-spacing: 0.02em; } -.parameter__osc span { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; +.parameter__reset { + color: var(--app-muted); } .parameter__osc svg, @@ -946,29 +956,89 @@ pre { color: var(--app-warning); } +.parameter__control { + position: relative; + min-width: 0; +} + .parameter__pair { display: grid; - grid-template-columns: repeat(auto-fit, minmax(5.125rem, 1fr)); + grid-template-columns: minmax(8rem, 1fr) minmax(5.25rem, 7rem); gap: 0.5rem; align-items: center; } +.parameter__pair--vec2 { + grid-template-columns: repeat(2, minmax(5.25rem, 1fr)); +} + .parameter__pair input[type="range"] { min-width: 7.5rem; } -.parameter__wheel-row { +.parameter__color-compact { display: grid; - grid-template-columns: minmax(0, 196px); - gap: 0.625rem; - align-items: start; - justify-content: center; + grid-template-columns: auto minmax(0, 1fr); + gap: 0.5rem; + align-items: end; } -.parameter__color-stack { +.parameter__swatch-button { + width: 42px; + min-width: 42px; + height: 42px; + min-height: 42px; + padding: 0.25rem; + border-color: var(--app-border); + background: var(--app-surface-2); +} + +.parameter__swatch-button:hover:not(:disabled) { + background: var(--app-surface-2); + border-color: rgba(26, 156, 219, 0.55); +} + +.parameter__swatch { + display: block; + width: 100%; + min-height: 100%; + border: 1px solid rgba(255, 255, 255, 0.28); + border-radius: var(--app-radius-sm); +} + +.parameter__rgba-grid { + display: grid; + grid-template-columns: repeat(4, minmax(3.5rem, 1fr)); + gap: 0.35rem; +} + +.parameter__rgba-field { + display: grid; + gap: 0.15rem; + color: var(--app-muted); + font-size: 0.68rem; + font-weight: 700; +} + +.parameter__rgba-field input { + min-height: 32px; + padding: 0.35rem 0.45rem; + font-size: 0.82rem; +} + +.parameter__color-popover { + position: absolute; + z-index: 20; + top: calc(100% + 0.45rem); + left: 0; display: grid; gap: 0.625rem; - width: 196px; + width: 224px; + padding: 0.75rem; + border: 1px solid var(--app-border); + border-radius: var(--app-radius); + background: #10151d; + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45); } .parameter__wheel { @@ -988,24 +1058,13 @@ pre { display: block; } -.parameter__color-bottom { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(4.5rem, 0.85fr); - gap: 0.625rem; - align-items: end; - width: 196px; -} - -.parameter__swatch { - width: 100%; - min-height: 38px; - border: 1px solid var(--app-border); - border-radius: var(--app-radius-sm); -} - .parameter__value-slider { - display: block; + display: grid; + gap: 0.25rem; width: 196px; + color: var(--app-muted); + font-size: 0.72rem; + font-weight: 700; } .parameter__value-slider input[type="range"] { @@ -1064,10 +1123,8 @@ pre { line-height: 1; } -.parameter__alpha { - display: grid; - gap: 0.25rem; - font-weight: 600; +.parameter__trigger { + min-width: 7rem; } .toggle { @@ -1156,8 +1213,8 @@ pre { .summary-grid, .kv-rows, .parameter-grid, - .parameter__header, - .parameter__wheel-row { + .parameter, + .parameter__header { grid-template-columns: 1fr; } @@ -1169,12 +1226,20 @@ pre { width: 24px; } - .parameter__swatch { - grid-column: auto; + .parameter__pair, + .parameter__color-compact { + grid-template-columns: 1fr; } - .parameter__color-stack, - .parameter__color-bottom, + .parameter__rgba-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .parameter__swatch-button { + width: 100%; + } + + .parameter__color-popover, .parameter__value-slider, .parameter__value-slider input[type="range"] { width: 100%;