From 8badd415b93929be49500bab01f32fa12ec4f111 Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Thu, 18 Jun 2026 12:45:45 -0400 Subject: [PATCH] =?UTF-8?q?feat(paint-slots):=20paint=20panel=20polish=20?= =?UTF-8?q?=E2=80=94=20sticky=20controls,=20selection=20outlines,=20auto-s?= =?UTF-8?q?elect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MaterialPaintPanel owns its scroll: the eraser/reset row stays pinned and the category tabs stick to the top, so only the material list scrolls. - Selected catalog swatch + active scene-material card use the same `ring-1 ring-primary ring-inset` outline as item/preset tiles. - Choosing a material category auto-selects its first material. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../ui/controls/material-paint-panel.tsx | 61 ++++++++++--------- .../ui/controls/material-picker.tsx | 14 +++-- .../ui/controls/scene-material-list.tsx | 10 ++- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/packages/editor/src/components/ui/controls/material-paint-panel.tsx b/packages/editor/src/components/ui/controls/material-paint-panel.tsx index d2fd2d24..9550cb97 100644 --- a/packages/editor/src/components/ui/controls/material-paint-panel.tsx +++ b/packages/editor/src/components/ui/controls/material-paint-panel.tsx @@ -56,8 +56,11 @@ export function MaterialPaintPanel() { } return ( -
-
+ // Fill the host's scroll slot and own the scroll internally: the eraser / + // reset row stays pinned (shrink-0) while only the material list below + // scrolls. The category tabs pin too (sticky, inside the scroll region). +
+
- { - // Custom-create: pre-create a scene material and select it as the - // brush via a `scene:` ref so painting stores the ref and edits to - // it propagate everywhere. The user edits it inline in the scene- - // material list below (auto-opened) — no separate right-side pane. - const id = generateSceneMaterialId() - const count = Object.keys(useScene.getState().materials).length - useScene.getState().addSceneMaterial({ id, name: `Material ${count + 1}`, material }) - setActivePaintMaterial({ - materialPreset: toSceneMaterialRef(id), - sourceTarget: activePaintTarget, - }) - setAutoEditMaterialId(id) - }} - onSelectMaterialPreset={(materialPreset) => { - setActivePaintMaterial({ materialPreset, sourceTarget: activePaintTarget }) - }} - selectedMaterialPreset={activePaintMaterial?.materialPreset} - value={activePaintMaterial?.material} - /> - {materialCount > 0 ? ( - - - - ) : null} +
+ { + // Custom-create: pre-create a scene material and select it as the + // brush via a `scene:` ref so painting stores the ref and edits to + // it propagate everywhere. The user edits it inline in the scene- + // material list below (auto-opened) — no separate right-side pane. + const id = generateSceneMaterialId() + const count = Object.keys(useScene.getState().materials).length + useScene.getState().addSceneMaterial({ id, name: `Material ${count + 1}`, material }) + setActivePaintMaterial({ + materialPreset: toSceneMaterialRef(id), + sourceTarget: activePaintTarget, + }) + setAutoEditMaterialId(id) + }} + onSelectMaterialPreset={(materialPreset) => { + setActivePaintMaterial({ materialPreset, sourceTarget: activePaintTarget }) + }} + selectedMaterialPreset={activePaintMaterial?.materialPreset} + value={activePaintMaterial?.material} + /> + {materialCount > 0 ? ( + + + + ) : null} +
) } diff --git a/packages/editor/src/components/ui/controls/material-picker.tsx b/packages/editor/src/components/ui/controls/material-picker.tsx index e0b5469f..6dd019e6 100644 --- a/packages/editor/src/components/ui/controls/material-picker.tsx +++ b/packages/editor/src/components/ui/controls/material-picker.tsx @@ -96,7 +96,7 @@ export function MaterialPicker({
{(catalogItems.length > 0 || onChange) && (
-
+
{availableCategories.map((category) => (