feat(ui): add flexible size and ColGrip to all studio columns and tabs

This commit is contained in:
2026-10-16 20:43:08 +07:00
parent 0e0361b843
commit 12ba33f78a
3 changed files with 38 additions and 16 deletions
+15 -8
View File
@@ -3061,7 +3061,7 @@ export function Workspace() {
},
},
wmSize: {
label: 'TEXT SIZE', off: '1', value: String(markStyle.size),
label: 'TEXT SIZE', off: '1', value: typeof markStyle.size === 'number' ? `${Number(markStyle.size.toFixed(2))}` : String(markStyle.size),
options: WM_SIZES,
onPick: (v) => {
remember();
@@ -4508,10 +4508,14 @@ export function Workspace() {
)}
</>
)}
{/* MY PHOTOS and FAVORITED are lists of names rather than buttons, so
their column is the visitor's to widen (see ColGrip). */}
{listTab ? <ColGrip col="main" /> : null}
{tab === 'light' ? <ColGrip col="dev" min={320} max={600} /> : null}
{/* Every tab's column is resizable */}
{tab === 'light' ? (
<ColGrip col="dev" min={320} max={600} />
) : listTab ? (
<ColGrip col="main" min={168} max={550} />
) : (
<ColGrip col={`main-${tab}`} min={168} max={550} />
)}
{tab === 'favorited' && saved.length === 0 ? <p className="hint">{t('sec.savedEmpty')}</p> : null}
{/* RESET is the way out of an edit, not one more chip: it sits under
@@ -4599,6 +4603,7 @@ export function Workspace() {
/>
) : null}
</div>
<ColGrip col="wm" min={200} max={600} />
</div>
) : null}
@@ -4606,9 +4611,7 @@ export function Workspace() {
{optGroup ? (
<div className="col col-sub strip" data-col="options">
<ChipRow chips={stripChips(optGroup)} list={optGroup === 'style'} glyph="◉" />
{/* PHOTO STYLE is one name per look, so its strip is the visitor's
to widen — the sims' names are longer than the column. */}
{optGroup === 'style' ? <ColGrip col="options" /> : null}
<ColGrip col={optGroup === 'style' ? 'options' : `options-${optGroup}`} min={168} max={550} />
{/* A watermark's colour: the presets above are a shortcut, the
well under them picks any colour at all. */}
{optGroup === 'wmColor' || optGroup === 'gpsColor' ? (
@@ -4646,6 +4649,7 @@ export function Workspace() {
{maskRulers.map((def) => (
<SliderRow key={def.key} slider={def} />
))}
<ColGrip col="mask" min={220} max={600} />
</div>
) : null}
{tab === 'presets' && showRecipes ? (
@@ -4707,6 +4711,7 @@ export function Workspace() {
>
{t('myp.remove')}
</button>
<ColGrip col="history" min={168} max={500} />
</div>
) : null}
@@ -4845,6 +4850,7 @@ export function Workspace() {
{t('frame.remove')}
</button>
</div>
<ColGrip col="custom-frame" min={240} max={600} />
</div>
) : null}
@@ -4861,6 +4867,7 @@ export function Workspace() {
{slider ? (
<div className="col col-slider" data-col="slider">
<SliderRow slider={slider} />
<ColGrip col="slider" min={220} max={600} />
</div>
) : null}
</div>
+15 -8
View File
@@ -110,7 +110,9 @@
overflow-y: hidden;
}
.col {
width: var(--col-w);
min-width: var(--col-w);
width: fit-content;
max-width: 50vw;
flex: 0 0 auto;
height: 100%;
max-height: 100%;
@@ -174,9 +176,9 @@
}
.col-grip:hover, .col-grip:active { background: var(--accent-soft); }
.col:last-child { border-right: none; }
.col-slider { width: var(--slider-w); }
.col-slider { min-width: var(--slider-w); width: fit-content; }
/* CREATE RECIPES draws a two-up form, so its column is the wide one. */
.col-create { width: 300px; }
.col-create { min-width: 300px; width: fit-content; }
.col-sub { background: var(--bg-elev); }
.reset-row {
margin-top: 6px;
@@ -204,11 +206,13 @@
background: var(--border-soft);
}
/* In a column the chips stack: one chip per row, full width. */
.col .chip-row { flex-direction: column; align-items: stretch; }
.col .chip-row { flex-direction: column; align-items: stretch; width: 100%; }
.col .chip {
justify-content: space-between;
text-align: left;
min-width: 0;
width: 100%;
white-space: nowrap;
}
.col .chip .chip-label {
white-space: nowrap;
@@ -216,6 +220,11 @@
text-overflow: ellipsis;
min-width: 0;
}
.col .chip .val {
flex-shrink: 0;
white-space: nowrap;
margin-left: 8px;
}
/* A row of one KIND of value read against each other, not a strip to scan: WB's
presets, laid out as a table of buttons instead of a wrapping row. */
.chip-row.grid {
@@ -318,10 +327,8 @@
}
/* UNDO/REDO are one glyph each, so the pair reads as a single control. */
.header .btn.icon { padding: 4px 9px; font-size: 15px; line-height: 1.2; }
/* WATERMARK's own column: its chips carry the longest labels in the app
("GPS WATERMARK OFF", "CUSTOM WATERMARK OFF" + PRO), which wrap in the
default column width. */
.wm-extra { border-right-color: var(--accent-line); width: 200px; }
/* WATERMARK's own column: flexible size with min-width so all text/buttons fit completely */
.wm-extra { border-right-color: var(--accent-line); min-width: 250px; width: fit-content; }
/* The watermark panel is two collapses, one per mark: each header chip stands
on its own controls (colour, face, switches, fields), and a rule keeps the
two apart while both marks are on. */
+8
View File
@@ -165,6 +165,14 @@ export function ColGrip({ col, min = 110, max = 560 }: { col: string; min?: numb
role="separator"
aria-orientation="vertical"
aria-label={`resize ${col}`}
title="Drag to resize column (double-click to auto-fit)"
onDoubleClick={() => {
const box = ref.current?.parentElement;
if (box) {
box.style.width = '';
keep(key, '');
}
}}
onPointerDown={(e) => {
const box = ref.current?.parentElement;
if (!box) return;