style: stack per-class override rows instead of a wide table (REQ-181 layout)
The width:100% table plus the new MaxBox column let the Class column absorb the slack, stranding the Container checkbox away from its class. One block per class now: name + Container checkbox on the first line, Conf/IoU/MinBox/ MaxBox inputs in a wrapping grid below. Behavior identical - KEYS, buildClassParams, compose() copy line, toggleContainer revert, aria labels.
This commit is contained in:
1 parent
d3a6aa49b6
commit
2971f9192c
4 files changed
+75
-61
No files matched your search
@@ -92,64 +92,56 @@ export default function ClassParamsTable({ classNames, globals, value, onChange,
|
||||
<span aria-live="polite">{copied ? 'Copied' : 'Copy'}</span>
|
||||
</button>
|
||||
</div>
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="hint" style={{ fontWeight: 400, fontSize: '0.74rem', textAlign: 'left', padding: '2px 4px' }}>Class</th>
|
||||
{KEYS.map(k => (
|
||||
<th key={k.key} className="hint" style={{ fontWeight: 400, fontSize: '0.74rem', color: k.color, padding: '2px 4px' }}>{k.label}</th>
|
||||
))}
|
||||
{project && (
|
||||
<th className="hint" style={{ fontWeight: 400, fontSize: '0.74rem', textAlign: 'left', padding: '2px 4px' }}>Container</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* Stacked rows (REQ-181): the name line carries the container flag, the
|
||||
grid below it the four overrides, so a wide class list never squeezes
|
||||
the numbers or strands the checkbox away from its class. */}
|
||||
<div>
|
||||
{classNames.map(name => {
|
||||
const cls = project?.classes.find(c => c.name === name)
|
||||
return (
|
||||
<tr key={name}>
|
||||
<td className="mono" style={{ fontSize: '0.76rem', padding: '2px 4px' }}>{name}</td>
|
||||
{KEYS.map(({ key, label, step, color }) => (
|
||||
<td key={key} style={{ padding: '2px 4px' }}>
|
||||
<input
|
||||
type="number"
|
||||
value={value[name]?.[key] ?? ''}
|
||||
min={0}
|
||||
max={1}
|
||||
step={step}
|
||||
placeholder={String(globals[key])}
|
||||
title={`Empty = use the global value (${globals[key]})`}
|
||||
aria-label={`${name} ${label} override, empty uses global ${globals[key]}`}
|
||||
onChange={(e) => set(name, key, e.target.value)}
|
||||
style={{
|
||||
width: 64, fontSize: '0.76rem', background: '#09090b', color,
|
||||
border: '1px solid #3f3f46', borderRadius: 4, padding: '2px 4px',
|
||||
cursor: 'text',
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
))}
|
||||
{project && (
|
||||
<td style={{ padding: '2px 4px', textAlign: 'center' }}>
|
||||
{cls && (
|
||||
<label title={`Keep boxes inside ${name} when auto-annotating (containment is not overlap)`} style={{ cursor: 'pointer', display: 'inline-flex' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={containers.has(name)}
|
||||
onChange={() => toggleContainer(cls)}
|
||||
aria-label={`Mark ${name} as container`}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
</label>
|
||||
)}
|
||||
</td>
|
||||
)}
|
||||
</tr>
|
||||
<div key={name} style={{ padding: '6px 0', borderBottom: '1px solid #27272a' }}>
|
||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
|
||||
<span className="mono" style={{ fontSize: '0.76rem', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</span>
|
||||
{project && cls && (
|
||||
<label title={`Keep boxes inside ${name} when auto-annotating (containment is not overlap)`} style={{ cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 4, flexShrink: 0, fontSize: '0.74rem' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={containers.has(name)}
|
||||
onChange={() => toggleContainer(cls)}
|
||||
aria-label={`Mark ${name} as container`}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
Container
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(118px, 1fr))', gap: 6, marginTop: 4 }}>
|
||||
{KEYS.map(({ key, label, step, color }) => (
|
||||
<label key={key} style={{ display: 'flex', alignItems: 'center', gap: 4, minWidth: 0, marginBottom: 0 }}>
|
||||
<span className="hint" style={{ fontSize: '0.7rem', color, whiteSpace: 'nowrap' }}>{label}</span>
|
||||
<input
|
||||
type="number"
|
||||
value={value[name]?.[key] ?? ''}
|
||||
min={0}
|
||||
max={1}
|
||||
step={step}
|
||||
placeholder={String(globals[key])}
|
||||
title={`Empty = use the global value (${globals[key]})`}
|
||||
aria-label={`${name} ${label} override, empty uses global ${globals[key]}`}
|
||||
onChange={(e) => set(name, key, e.target.value)}
|
||||
style={{
|
||||
width: '100%', minWidth: 0, fontSize: '0.76rem', background: '#09090b', color,
|
||||
border: '1px solid #3f3f46', borderRadius: 4, padding: '2px 4px',
|
||||
cursor: 'text',
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user