sqlite-hub 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -83,8 +83,10 @@ import {
83
83
  selectConnection,
84
84
  selectQueryHistoryItem,
85
85
  selectStructureEntry,
86
+ setDocumentsSearchQuery,
86
87
  setTableDesignerSearchQuery,
87
88
  setTableDesignerSqlPreviewVisibility,
89
+ toggleTableDesignerTablesPanel,
88
90
  setDataTableSearchQuery,
89
91
  setStructureTableSearchQuery,
90
92
  toggleStructureTablesPanel,
@@ -376,21 +378,19 @@ function syncMediaTaggingCurrentMediaUi(button, detailsVisible) {
376
378
  }
377
379
 
378
380
  const nextVisible = Boolean(detailsVisible);
379
- const expandedLabel = button.dataset.expandedLabel || 'Shrink Media Viewer';
380
- const collapsedLabel = button.dataset.collapsedLabel || 'Show Media Viewer';
381
+ const expandedLabel = button.dataset.expandedLabel || 'Hide Viewer';
382
+ const collapsedLabel = button.dataset.collapsedLabel || 'Show Viewer';
381
383
  preview.classList.toggle('media-tagging-preview--meta-hidden', !nextVisible);
384
+ button.classList.toggle('is-active', !nextVisible);
382
385
  button.dataset.nextValue = nextVisible ? 'false' : 'true';
383
386
  button.setAttribute('aria-expanded', nextVisible ? 'true' : 'false');
387
+ button.setAttribute('aria-pressed', nextVisible ? 'false' : 'true');
384
388
 
385
- if (nextVisible) {
386
- const icon = document.createElement('span');
389
+ const icon = document.createElement('span');
387
390
 
388
- icon.className = 'material-symbols-outlined';
389
- icon.textContent = 'visibility_off';
390
- button.replaceChildren(icon, document.createTextNode(` ${expandedLabel}`));
391
- } else {
392
- button.textContent = collapsedLabel;
393
- }
391
+ icon.className = 'material-symbols-outlined';
392
+ icon.textContent = nextVisible ? 'visibility_off' : 'visibility';
393
+ button.replaceChildren(icon, document.createTextNode(` ${nextVisible ? expandedLabel : collapsedLabel}`));
394
394
 
395
395
  return true;
396
396
  }
@@ -2656,6 +2656,9 @@ async function handleAction(actionNode) {
2656
2656
  case 'toggle-structure-tables':
2657
2657
  toggleStructureTablesPanel();
2658
2658
  return;
2659
+ case 'toggle-table-designer-tables':
2660
+ toggleTableDesignerTablesPanel();
2661
+ return;
2659
2662
  case 'select-structure-entry':
2660
2663
  if (actionNode.dataset.entryName) {
2661
2664
  await selectStructureEntry(actionNode.dataset.entryName);
@@ -2989,6 +2992,18 @@ document.addEventListener('keydown', event => {
2989
2992
  return;
2990
2993
  }
2991
2994
 
2995
+ if (state.route.name === 'charts' && state.charts.detailPanelVisible) {
2996
+ event.preventDefault();
2997
+ setChartsDetailPanelVisibility(false);
2998
+ return;
2999
+ }
3000
+
3001
+ if (state.editor.historySelectedId !== null || state.editor.historyDetail) {
3002
+ event.preventDefault();
3003
+ clearQueryHistorySelection();
3004
+ return;
3005
+ }
3006
+
2992
3007
  if (
2993
3008
  state.route.name === 'data' &&
2994
3009
  (typeof state.dataBrowser.selectedRowIndex === 'number' || Boolean(state.dataBrowser.selectedRow))
@@ -3051,6 +3066,11 @@ document.addEventListener('input', event => {
3051
3066
  return;
3052
3067
  }
3053
3068
 
3069
+ if (bindNode.dataset.bind === 'documents-search') {
3070
+ setDocumentsSearchQuery(bindNode.value);
3071
+ return;
3072
+ }
3073
+
3054
3074
  if (bindNode.dataset.bind === 'data-search-query') {
3055
3075
  void setDataSearchQuery(bindNode.value);
3056
3076
  return;
@@ -45,7 +45,8 @@ export function renderQueryEditor({
45
45
  const secondaryButtonClass = "standard-button";
46
46
  const left = `
47
47
  <button
48
- class="${secondaryButtonClass}"
48
+ class="${secondaryButtonClass} panel-toggle-button ${editorVisible ? "" : "is-active"}"
49
+ aria-pressed="${editorVisible ? "false" : "true"}"
49
50
  data-action="toggle-editor-panel"
50
51
  data-next-value="${editorVisible ? "false" : "true"}"
51
52
  type="button"
@@ -90,7 +91,8 @@ export function renderQueryEditor({
90
91
 
91
92
  const right = `
92
93
  <button
93
- class="${secondaryButtonClass}"
94
+ class="${secondaryButtonClass} panel-toggle-button ${historyVisible ? "" : "is-active"}"
95
+ aria-pressed="${historyVisible ? "false" : "true"}"
94
96
  data-action="toggle-query-history-panel"
95
97
  data-next-value="${historyVisible ? "false" : "true"}"
96
98
  type="button"
@@ -102,7 +104,7 @@ export function renderQueryEditor({
102
104
 
103
105
  return `
104
106
  <div class="flex h-full min-h-0 flex-col">
105
- <div class="bg-surface-container-low px-6 py-3">
107
+ <div class="workspace-header workspace-header--low">
106
108
  <div class="query-editor-toolbar">
107
109
  <div class="query-editor-toolbar__left">${left}</div>
108
110
  <div class="query-editor-toolbar__center">${center}</div>
@@ -966,6 +966,7 @@ function updateInspectorToggleButton() {
966
966
  }
967
967
 
968
968
  currentGraph.inspectorToggleButton.classList.toggle('is-active', currentGraph.inspectorHidden);
969
+ currentGraph.inspectorToggleButton.setAttribute('aria-pressed', currentGraph.inspectorHidden ? 'true' : 'false');
969
970
  const icon = document.createElement('span');
970
971
  const label = currentGraph.inspectorHidden ? 'Show Inspector' : 'Hide Inspector';
971
972
 
@@ -323,7 +323,6 @@ export function renderTableDesignerEditor(state) {
323
323
  }
324
324
 
325
325
  const catalogTables = state.tableDesigner.tables ?? [];
326
- const visibleColumns = draft.columns.filter((column) => !column.deleted);
327
326
  const saveLabel =
328
327
  draft.mode === "create"
329
328
  ? state.tableDesigner.saving
@@ -335,11 +334,12 @@ export function renderTableDesignerEditor(state) {
335
334
 
336
335
  return `
337
336
  <section class="table-designer-main shell-section">
338
- <header class="table-designer-main__header">
339
- <div>
340
- <div class="table-designer-main__eyebrow">
341
- ${draft.mode === "create" ? "New Table Draft" : "Editing Existing Table"}
342
- </div>
337
+ <div data-table-designer-feedback>
338
+ ${renderTableDesignerFeedback(draft, state.tableDesigner.saveError)}
339
+ </div>
340
+
341
+ <section class="table-designer-main__section">
342
+ <div class="table-designer-main__section-header">
343
343
  <div class="table-designer-main__title-row">
344
344
  <input
345
345
  class="table-designer-main__name"
@@ -356,42 +356,6 @@ export function renderTableDesignerEditor(state) {
356
356
  : ""
357
357
  }
358
358
  </div>
359
- <div class="table-designer-main__subtitle">
360
- ${escapeHtml(String(visibleColumns.length))} visible column${
361
- visibleColumns.length === 1 ? "" : "s"
362
- } // Table Designer v2 // SQLite-safe operations only
363
- </div>
364
- </div>
365
- <div class="table-designer-main__actions">
366
- ${renderFillToggle(draft)}
367
- <button
368
- class="standard-button"
369
- data-action="refresh-view"
370
- type="button"
371
- >
372
- Reload Schema
373
- </button>
374
- <button
375
- class="standard-button"
376
- data-action="save-table-designer"
377
- data-table-designer-save-button
378
- ${draft.canSave ? "" : "disabled"}
379
- type="button"
380
- >
381
- ${escapeHtml(saveLabel)}
382
- </button>
383
- </div>
384
- </header>
385
-
386
- <div data-table-designer-feedback>
387
- ${renderTableDesignerFeedback(draft, state.tableDesigner.saveError)}
388
- </div>
389
-
390
- <section class="table-designer-main__section">
391
- <div class="table-designer-main__section-header">
392
- <div>
393
- <div class="table-designer-main__section-title">Columns</div>
394
- </div>
395
359
  <div class="table-designer-main__section-actions">
396
360
  <button
397
361
  class="standard-button"
@@ -400,6 +364,23 @@ export function renderTableDesignerEditor(state) {
400
364
  >
401
365
  + Add Column
402
366
  </button>
367
+ <button
368
+ class="standard-button"
369
+ data-action="refresh-view"
370
+ type="button"
371
+ >
372
+ Reload Schema
373
+ </button>
374
+ <button
375
+ class="standard-button"
376
+ data-action="save-table-designer"
377
+ data-table-designer-save-button
378
+ ${draft.canSave ? "" : "disabled"}
379
+ type="button"
380
+ >
381
+ ${escapeHtml(saveLabel)}
382
+ </button>
383
+ ${renderFillToggle(draft)}
403
384
  </div>
404
385
  </div>
405
386
  ${renderColumnGrid(draft, catalogTables)}
@@ -18,38 +18,14 @@ export function renderTableDesignerSidebar(state) {
18
18
  const isNewDraft = state.tableDesigner.draft?.mode === 'create';
19
19
 
20
20
  return `
21
- <aside class="table-designer-sidebar">
22
- <div class="table-designer-sidebar__header">
21
+ <aside class="table-designer-sidebar subnavi-panel">
22
+ <div class="table-designer-sidebar__header subnavi-header">
23
23
  <div>
24
- <div class="table-designer-sidebar__eyebrow">Table Designer</div>
25
- <div class="table-designer-sidebar__meta">
24
+ <div class="subnavi-header-title">Table Designer</div>
25
+ <div class="subnavi-header-details">
26
26
  ${escapeHtml(formatNumber(tables.length))} table${tables.length === 1 ? '' : 's'}
27
27
  </div>
28
28
  </div>
29
- <div class="table-designer-sidebar__header-actions">
30
- <button
31
- class="standard-button"
32
- data-action="import-table-designer-csv"
33
- type="button"
34
- >
35
- Import CSV
36
- </button>
37
- <input
38
- accept=".csv,text/csv"
39
- class="table-designer-sidebar__file-input"
40
- data-bind="table-designer-import-file"
41
- type="file"
42
- />
43
- <button
44
- class="signature-button"
45
- data-action="navigate"
46
- data-to="/table-designer/new"
47
- type="button"
48
- >
49
- + New Table
50
- </button>
51
-
52
- </div>
53
29
  </div>
54
30
 
55
31
  <label class="table-designer-sidebar__search">
@@ -64,7 +40,7 @@ export function renderTableDesignerSidebar(state) {
64
40
  />
65
41
  </label>
66
42
 
67
- <div class="table-designer-sidebar__list custom-scrollbar">
43
+ <div class="table-designer-sidebar__list subnavi-list custom-scrollbar">
68
44
  ${
69
45
  state.tableDesigner.loading && !tables.length
70
46
  ? `
@@ -76,7 +52,7 @@ export function renderTableDesignerSidebar(state) {
76
52
  : isNewDraft
77
53
  ? `
78
54
  <button
79
- class="table-designer-sidebar__item is-active w-full border border-primary-container/30 bg-surface-container-high px-4 py-3 text-left transition-colors"
55
+ class="table-designer-sidebar__item subnavi-item is-active border border-primary-container/30 bg-surface-container-high px-4 py-3 text-left transition-colors"
80
56
  data-action="navigate"
81
57
  data-to="/table-designer/new"
82
58
  type="button"
@@ -102,7 +78,7 @@ export function renderTableDesignerSidebar(state) {
102
78
  .map(
103
79
  table => `
104
80
  <button
105
- class="table-designer-sidebar__item w-full border px-4 py-3 text-left transition-colors ${
81
+ class="table-designer-sidebar__item subnavi-item border px-4 py-3 text-left transition-colors ${
106
82
  !isNewDraft && table.name === state.tableDesigner.selectedTableName
107
83
  ? 'is-active border-primary-container/30 bg-surface-container-high'
108
84
  : 'border-outline-variant/10 bg-surface-container-lowest hover:bg-surface-container-high'
@@ -23,7 +23,8 @@ function renderPreviewHeader(draft, isVisible) {
23
23
  : ''
24
24
  }
25
25
  <button
26
- class="standard-button"
26
+ class="standard-button panel-toggle-button ${isVisible ? '' : 'is-active'}"
27
+ aria-pressed="${isVisible ? 'false' : 'true'}"
27
28
  data-action="toggle-table-designer-sql-preview"
28
29
  data-next-value="${isVisible ? 'false' : 'true'}"
29
30
  type="button"
@@ -51,9 +51,11 @@ const UI_PREFERENCE_STORAGE_KEYS = {
51
51
  chartsHistoryVisible: 'sqlite_hub_charts_history_visible',
52
52
  chartsQueryVisible: 'sqlite_hub_charts_query_visible',
53
53
  chartsResultsVisible: 'sqlite_hub_charts_results_visible',
54
+ tableDesignerTablesVisible: 'sqlite_hub_table_designer_tables_visible',
54
55
  tableDesignerSqlPreviewVisible: 'sqlite_hub_table_designer_sql_preview_visible',
55
56
  documentsEditorVisible: 'sqlite_hub_documents_editor_visible',
56
57
  documentsPreviewVisible: 'sqlite_hub_documents_preview_visible',
58
+ mediaTaggingViewerVisible: 'sqlite_hub_media_tagging_viewer_visible',
57
59
  };
58
60
  const QUERY_HISTORY_PAGE_SIZE = 30;
59
61
  const QUERY_HISTORY_RUN_LIMIT = 8;
@@ -356,6 +358,7 @@ const state = {
356
358
  items: [],
357
359
  selectedId: null,
358
360
  selected: null,
361
+ searchQuery: '',
359
362
  draftFilename: '',
360
363
  draftContent: '',
361
364
  dirty: false,
@@ -372,6 +375,7 @@ const state = {
372
375
  tables: [],
373
376
  selectedTableName: null,
374
377
  draft: null,
378
+ tablesVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true),
375
379
  sqlPreviewVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true),
376
380
  pendingImportedDraft: null,
377
381
  loading: false,
@@ -424,7 +428,7 @@ const state = {
424
428
  issues: [],
425
429
  dismissedIssueKeys: [],
426
430
  selectedTagKeys: [],
427
- workflowMediaDetailsVisible: true,
431
+ workflowMediaDetailsVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible, true),
428
432
  workflowMediaRotationDegrees: 0,
429
433
  skippedMediaKeys: [],
430
434
  tagFormValues: {},
@@ -959,6 +963,7 @@ function resetDocumentsState() {
959
963
  state.documents.items = [];
960
964
  state.documents.selectedId = null;
961
965
  state.documents.selected = null;
966
+ state.documents.searchQuery = '';
962
967
  state.documents.draftFilename = '';
963
968
  state.documents.draftContent = '';
964
969
  state.documents.dirty = false;
@@ -1189,6 +1194,7 @@ function setMissingDatabaseState() {
1189
1194
  state.tableDesigner.tables = [];
1190
1195
  state.tableDesigner.selectedTableName = null;
1191
1196
  state.tableDesigner.draft = null;
1197
+ state.tableDesigner.tablesVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true);
1192
1198
  state.tableDesigner.sqlPreviewVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true);
1193
1199
  state.tableDesigner.pendingImportedDraft = null;
1194
1200
  state.tableDesigner.saving = false;
@@ -2384,6 +2390,7 @@ function invalidateDatabaseCaches(options = {}) {
2384
2390
  state.tableDesigner.tables = [];
2385
2391
  state.tableDesigner.selectedTableName = null;
2386
2392
  state.tableDesigner.draft = null;
2393
+ state.tableDesigner.tablesVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true);
2387
2394
  state.tableDesigner.sqlPreviewVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true);
2388
2395
  state.tableDesigner.pendingImportedDraft = null;
2389
2396
  state.tableDesigner.saving = false;
@@ -2428,6 +2435,10 @@ function invalidateDatabaseCaches(options = {}) {
2428
2435
  state.mediaTagging.issues = [];
2429
2436
  state.mediaTagging.dismissedIssueKeys = [];
2430
2437
  state.mediaTagging.selectedTagKeys = [];
2438
+ state.mediaTagging.workflowMediaDetailsVisible = readStoredBoolean(
2439
+ UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible,
2440
+ true,
2441
+ );
2431
2442
  state.mediaTagging.workflowMediaRotationDegrees = 0;
2432
2443
  state.mediaTagging.skippedMediaKeys = [];
2433
2444
  state.mediaTagging.tagFormValues = {};
@@ -4108,6 +4119,12 @@ export function setTableDesignerSearchQuery(query) {
4108
4119
  emitChange();
4109
4120
  }
4110
4121
 
4122
+ export function toggleTableDesignerTablesPanel() {
4123
+ state.tableDesigner.tablesVisible = state.tableDesigner.tablesVisible === false;
4124
+ storeBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, state.tableDesigner.tablesVisible);
4125
+ emitChange();
4126
+ }
4127
+
4111
4128
  export function setDataTableSearchQuery(query) {
4112
4129
  state.dataBrowser.tableSearchQuery = String(query ?? '');
4113
4130
  emitChange();
@@ -4118,6 +4135,11 @@ export function setStructureTableSearchQuery(query) {
4118
4135
  emitChange();
4119
4136
  }
4120
4137
 
4138
+ export function setDocumentsSearchQuery(query) {
4139
+ state.documents.searchQuery = String(query ?? '');
4140
+ emitChange();
4141
+ }
4142
+
4121
4143
  export function setTableDesignerSqlPreviewVisibility(visible) {
4122
4144
  const nextValue = typeof visible === 'boolean' ? visible : !Boolean(state.tableDesigner.sqlPreviewVisible);
4123
4145
 
@@ -4359,6 +4381,7 @@ export function setMediaTaggingWorkflowMediaDetailsVisible(value, options = {})
4359
4381
  }
4360
4382
 
4361
4383
  state.mediaTagging.workflowMediaDetailsVisible = nextValue;
4384
+ storeBoolean(UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible, nextValue);
4362
4385
 
4363
4386
  if (options.notify !== false) {
4364
4387
  emitChange();
@@ -170,10 +170,10 @@ function renderChartsList(state) {
170
170
  hasSearch
171
171
  ? 'Try another title, SQL fragment, chart type, or saved status.'
172
172
  : isSavedTab
173
- ? 'Save chartable queries from this list or from the SQL Editor to keep them here.'
174
- : isUnsavedTab
175
- ? 'Unsaved chartable queries will appear here until you bookmark them.'
176
- : 'Run SELECT queries in the SQL Editor first. They will appear here automatically.'
173
+ ? 'Save chartable queries from this list or from the SQL Editor to keep them here.'
174
+ : isUnsavedTab
175
+ ? 'Unsaved chartable queries will appear here until you bookmark them.'
176
+ : 'Run SELECT queries in the SQL Editor first. They will appear here automatically.'
177
177
  }
178
178
  </p>
179
179
  </div>
@@ -549,7 +549,7 @@ function renderChartCard(chart, state, analysis) {
549
549
  '<div class="flex flex-wrap items-center gap-2">',
550
550
  '<h3 class="truncate font-headline text-xl font-black uppercase tracking-tight text-on-surface">',
551
551
  escapeHtml(chart.name),
552
- "</h3>",
552
+ '</h3>',
553
553
  renderStatusBadge(getQueryChartTypeLabel(chart.chartType), 'primary'),
554
554
  '</div></div><div class="flex flex-wrap items-center gap-2">',
555
555
  '<button class="standard-button" data-action="open-edit-query-chart-modal" data-chart-id="',
@@ -563,8 +563,8 @@ function renderChartCard(chart, state, analysis) {
563
563
  '" type="button">Export PNG</button>',
564
564
  '</div></header><div class="query-chart-card__body">',
565
565
  renderChartSurface(chart, state, analysis),
566
- "</div></article>",
567
- ].join("");
566
+ '</div></article>',
567
+ ].join('');
568
568
  }
569
569
 
570
570
  export function renderChartsDetail(state) {
@@ -636,15 +636,16 @@ export function renderChartsDetail(state) {
636
636
  </div>
637
637
  <div class="charts-detail-shell__controls-group charts-detail-shell__controls-group--end">
638
638
  <button
639
- class="standard-button"
639
+ class="standard-button panel-toggle-button ${historyVisible ? '' : 'is-active'}"
640
+ aria-pressed="${historyVisible ? 'false' : 'true'}"
640
641
  data-action="toggle-query-history-panel"
641
642
  data-next-value="${historyVisible ? 'false' : 'true'}"
642
643
  type="button"
643
644
  >
644
645
  <span class="material-symbols-outlined text-sm">${
645
- historyVisible ? 'visibility_off' : 'visibility'
646
+ historyVisible ? 'visibility_off' : 'visibility'
646
647
  }</span>
647
- ${historyVisible ? 'Hide Query History' : 'Show Query History'}
648
+ ${historyVisible ? 'Hide History' : 'Show History'}
648
649
  </button>
649
650
  </div>
650
651
  </div>
@@ -78,31 +78,32 @@ function renderTableList(state) {
78
78
  }
79
79
 
80
80
  return `
81
- <div class="custom-scrollbar flex-1 overflow-auto px-4 py-4">
82
- <div class="space-y-2">
83
- ${filteredTables
84
- .map(
85
- table => `
86
- <button
87
- class="w-full border px-4 py-3 text-left transition-colors ${
88
- table.name === activeName
89
- ? 'border-primary-container/30 bg-surface-container-high'
90
- : 'border-outline-variant/10 bg-surface-container-lowest hover:bg-surface-container-high'
91
- }"
92
- data-action="navigate"
93
- data-to="/data/${encodeURIComponent(table.name)}"
94
- type="button"
95
- >
96
- <div class="truncate font-mono text-xs ${
97
- table.name === activeName ? 'text-primary-container' : 'text-on-surface'
98
- }">
99
- ${escapeHtml(table.name)}
100
- </div>
101
- </button>
102
- `,
103
- )
104
- .join('')}
105
- </div>
81
+ <div class="subnavi-list custom-scrollbar">
82
+ ${filteredTables
83
+ .map(
84
+ table => `
85
+ <button
86
+ class="table-designer-sidebar__item subnavi-item border px-4 py-3 text-left transition-colors ${
87
+ table.name === activeName
88
+ ? 'is-active border-primary-container/30 bg-surface-container-high'
89
+ : 'border-outline-variant/10 bg-surface-container-lowest hover:bg-surface-container-high'
90
+ }"
91
+ data-action="navigate"
92
+ data-to="/data/${encodeURIComponent(table.name)}"
93
+ type="button"
94
+ >
95
+ <div class="table-designer-sidebar__item-name ${table.name === activeName ? 'is-active' : ''}">
96
+ ${escapeHtml(table.name)}
97
+ </div>
98
+ <div class="mt-1 truncate text-[10px] uppercase tracking-[0.16em] text-on-surface-variant/45">
99
+ ${escapeHtml(formatNumber(table.columnCount ?? 0))} column${
100
+ Number(table.columnCount ?? 0) === 1 ? '' : 's'
101
+ }
102
+ </div>
103
+ </button>
104
+ `,
105
+ )
106
+ .join('')}
106
107
  </div>
107
108
  `;
108
109
  }
@@ -112,13 +113,14 @@ function renderWorkspaceHeader(state) {
112
113
  const tablesVisible = state.dataBrowser.tablesVisible !== false;
113
114
 
114
115
  return `
115
- <header class="border-b border-outline-variant/10 bg-surface-container px-6 py-3">
116
+ <header class="workspace-header">
116
117
  <div class="flex flex-wrap items-center justify-between gap-4">
117
118
  <div class="flex items-center gap-3">
118
119
  ${
119
120
  table
120
121
  ? `<button
121
- class="standard-button"
122
+ class="standard-button panel-toggle-button ${tablesVisible ? '' : 'is-active'}"
123
+ aria-pressed="${tablesVisible ? 'false' : 'true'}"
122
124
  data-action="toggle-data-tables"
123
125
  type="button"
124
126
  >
@@ -631,17 +633,17 @@ export function renderDataView(state) {
631
633
  return {
632
634
  main: `
633
635
  <section class="view-surface min-h-full bg-surface-container flex h-full min-h-0 flex-col overflow-hidden">
634
- <div class="grid h-full min-h-0 grid-cols-1 ${tablesVisible ? 'md:grid-cols-[18rem_minmax(0,1fr)]' : ''}">
636
+ <div class="data-view-grid ${tablesVisible ? 'data-view-grid--with-subnavi' : ''}">
635
637
  ${
636
638
  tablesVisible
637
639
  ? `
638
- <aside class="flex min-h-0 flex-col border-r border-outline-variant/10 bg-surface-low">
639
- <div class="border-b border-outline-variant/10 px-6 py-5">
640
- <div class="text-[10px] font-bold uppercase tracking-[0.2em] text-primary-container">
641
- Tables
642
- </div>
643
- <div class="mt-2 text-[10px] font-mono uppercase tracking-[0.16em] text-on-surface-variant/55">
644
- total ${escapeHtml(formatNumber(state.dataBrowser.tables.length))}
640
+ <aside class="data-view__sidebar subnavi-panel">
641
+ <div class="subnavi-header">
642
+ <div>
643
+ <div class="subnavi-header-title">Tables</div>
644
+ <div class="subnavi-header-details">
645
+ total ${escapeHtml(formatNumber(state.dataBrowser.tables.length))}
646
+ </div>
645
647
  </div>
646
648
  </div>
647
649
  ${renderDataTableSearch(state)}