web: accent the brand and add the studio's quick gestures

- the brand "Cam", the avatar and the signed-in name follow the theme accent
- double-click a slider track resets that parameter; double-click the photo
  toggles 1:1 and the whole photo on the stage
- `*`, or a recipe chip dragged onto the star, files the look under FAVORITED
- RESET under CREATE clears the draft form, and the button now sits under a
  rule at the foot of the column
This commit is contained in:
2026-09-18 12:09:06 +07:00
parent 0f52572f20
commit 567f650bbb
6 changed files with 144 additions and 9 deletions
+15
View File
@@ -14,6 +14,9 @@ export interface ChipDef {
amberValue?: boolean;
pro?: boolean;
disabled?: boolean;
// Present when the chip itself can be dragged somewhere: the payload the drop
// target reads back (the recipe's id, for the FAVORITED rail button).
drag?: string;
onClick: () => void;
}
@@ -31,6 +34,8 @@ export interface SliderDef {
// swatch under the ruler so the hue moves with the number. Absent = no swatch.
swatch?: string;
onChange: (value: number) => void;
// Double-clicking the track puts the parameter back to its default.
onReset: () => void;
// "<" — closes the ruler and reopens the strip it was launched from.
onBack: () => void;
}
@@ -46,6 +51,15 @@ export function ChipRow({ chips }: { chips: ChipDef[] }) {
className={`chip${chip.active ? ' on' : ''}${chip.amberValue ? ' amber' : ''}`}
aria-pressed={!!chip.active}
disabled={chip.disabled}
draggable={!!chip.drag}
onDragStart={
chip.drag
? (e) => {
e.dataTransfer.setData('text/plain', chip.drag!);
e.dataTransfer.effectAllowed = 'copy';
}
: undefined
}
onClick={chip.onClick}
>
{chip.label}
@@ -92,6 +106,7 @@ export function SliderRow({ slider }: { slider: SliderDef }) {
step={slider.step}
value={slider.value}
onChange={(e) => slider.onChange(Number(e.target.value))}
onDoubleClick={slider.onReset}
/>
{slider.swatch ? (
<div