Add per-table "hide chrome/headers when unfocused" clean-look option
New Settings checkbox: while a table isn't the selected canvas object, its title bar, column letters and row numbers disappear entirely -- not just visually, their reserved space collapses too, so the table shrinks to just its cell grid. Clicking back into it (e.g. any cell) reselects it and brings everything back. TableObject.hideChromeUnfocused (store/types.ts) + setTableHideChromeUnfocused (document.ts) + io/json.ts normalization, following the existing per-object appearance-setting pattern. CanvasObject.vue gates its title bar on a new showChrome computed and passes its existing `selected` prop down to TableGrid.vue (previously only took tableId) so it can make the same call for its own headers. TableGrid.vue's HEAD_W (a plain constant) becomes a `headW` computed, and the existing `headerH` computed now returns 0 for both whenever hidden -- sufficient on its own since rowTop()/colLeft() already sum those two values as their base offset and are the single source every other position calculation in the file (sticky-frozen offsets, the in-cell editor overlay, clip/fill marquees, scroll-into-view, row virtualization) already goes through. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2650,6 +2650,34 @@ describe('per-object background & text colour', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('table "hide chrome when unfocused" (clean-look presentation option)', () => {
|
||||
it('toggles hideChromeUnfocused and clears the field when turned off', () => {
|
||||
const s = fresh();
|
||||
const id = tableId(s, 'Umsatz');
|
||||
expect(s.tableById(id)!.hideChromeUnfocused).toBeUndefined();
|
||||
s.setTableHideChromeUnfocused(id, true);
|
||||
expect(s.tableById(id)!.hideChromeUnfocused).toBe(true);
|
||||
s.setTableHideChromeUnfocused(id, false);
|
||||
expect(s.tableById(id)!.hideChromeUnfocused).toBeUndefined(); // "unset", not stored as false
|
||||
});
|
||||
|
||||
it('survives a JSON round-trip; a non-boolean value on import is dropped', () => {
|
||||
const s = fresh();
|
||||
const id = tableId(s, 'Umsatz');
|
||||
s.setTableHideChromeUnfocused(id, true);
|
||||
const before = s.snapshot();
|
||||
s.replaceDocument(parseDocument(serializeDocument(before)));
|
||||
expect(s.snapshot()).toEqual(before);
|
||||
expect(s.tableById(id)!.hideChromeUnfocused).toBe(true);
|
||||
|
||||
const doc = JSON.parse(serializeDocument(s.snapshot()));
|
||||
const tbl = doc.sheets[0].objects.find((o: { id: string }) => o.id === id);
|
||||
tbl.hideChromeUnfocused = 'yes';
|
||||
s.replaceDocument(parseDocument(JSON.stringify(doc)));
|
||||
expect(s.tableById(id)!.hideChromeUnfocused).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('full-fidelity JSON export — backgrounds, formats, sheet settings', () => {
|
||||
/** Populate *every* persisted setting, then verify the export string carries
|
||||
* it and a round-trip is byte-for-byte identical. */
|
||||
@@ -2678,6 +2706,7 @@ describe('full-fidelity JSON export — backgrounds, formats, sheet settings', (
|
||||
s.setObjectLocale(umsatzId, 'fr-FR');
|
||||
s.setTableView(umsatzId, { mode: 'fixed', width: 520, height: 300, frozenRows: 1, frozenCols: 1 });
|
||||
s.setTableRowHeight(umsatzId, 30);
|
||||
s.setTableHideChromeUnfocused(umsatzId, true);
|
||||
s.setRowHeight(umsatzId, 4, 52);
|
||||
s.setColWidth(umsatzId, 0, 130);
|
||||
s.setRangeFormat(umsatzId, { col: 1, row: 1 }, { col: 3, row: 4 }, {
|
||||
@@ -2751,6 +2780,7 @@ describe('full-fidelity JSON export — backgrounds, formats, sheet settings', (
|
||||
rowHeights: { '4': 52 },
|
||||
colWidths: { '0': 130 },
|
||||
view: { mode: 'fixed', width: 520, height: 300, frozenRows: 1, frozenCols: 1 },
|
||||
hideChromeUnfocused: true,
|
||||
});
|
||||
expect(tbl.formats['1,1']).toEqual({
|
||||
align: 'right',
|
||||
|
||||
@@ -895,6 +895,13 @@ function createStore() {
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
function setTableHideChromeUnfocused(tableId: string, hide: boolean) {
|
||||
const t = tableById(tableId);
|
||||
if (!t) return;
|
||||
if (hide) t.hideChromeUnfocused = true;
|
||||
else delete t.hideChromeUnfocused;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
function setCsvDelimiter(d: ',' | ';') {
|
||||
doc.csvDelimiter = d === ';' ? ';' : ',';
|
||||
@@ -2944,6 +2951,7 @@ function createStore() {
|
||||
selectObject,
|
||||
setObjectBg,
|
||||
setObjectTextColor,
|
||||
setTableHideChromeUnfocused,
|
||||
// table grid
|
||||
tableById,
|
||||
cellInput,
|
||||
|
||||
@@ -86,6 +86,13 @@ export interface TableObject {
|
||||
bg?: string;
|
||||
/** object default text colour override */
|
||||
fg?: string;
|
||||
/** when true, this table's title bar and row/column headers are only
|
||||
* shown while it's the selected canvas object -- otherwise (including
|
||||
* right after the document loads, before anything is selected) they're
|
||||
* hidden entirely, not just visually: the table's footprint shrinks to
|
||||
* just its cell grid. A presentation/"clean look" option; unset/false =
|
||||
* always shown, today's behaviour. */
|
||||
hideChromeUnfocused?: boolean;
|
||||
}
|
||||
|
||||
/** A chart object placed on a sheet canvas. Freely positioned and resized. */
|
||||
|
||||
Reference in New Issue
Block a user