improved kv metacore
This commit is contained in:
@@ -522,3 +522,54 @@
|
||||
max-height: 160px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.kv-app-gear {
|
||||
margin-left: 0.25rem;
|
||||
font-size: 1.05rem;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.kv-app-gear:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.kv-modal-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: 4vh 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.kv-modal {
|
||||
position: relative;
|
||||
background: white;
|
||||
color: inherit;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
|
||||
width: min(960px, 100%);
|
||||
max-height: 92vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.kv-modal-close {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.75rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
opacity: 0.6;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.kv-modal-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { KVBranchEditor } from './KVBranchEditor';
|
||||
import { SearchFieldChips } from './SearchFieldChips';
|
||||
import { ToastStack, makeToast } from './Toast';
|
||||
import { ToastEntry } from './types';
|
||||
import { SnapshotPanel } from '../components/SnapshotPanel';
|
||||
import './KVApp.css';
|
||||
|
||||
const SEARCH_FIELDS_LS_KEY = 'kv-editor.searchFields.v1';
|
||||
@@ -28,6 +29,7 @@ function loadSearchFields(): string[] {
|
||||
//
|
||||
// A sticky header carries the search bar, the breadcrumb, and basic stats.
|
||||
export default function KVApp() {
|
||||
const [snapshotOpen, setSnapshotOpen] = useState(false);
|
||||
// Selected node. branchPath is set when a branch is selected; selectedKey
|
||||
// when a leaf is. Mutually exclusive.
|
||||
const [selectedKey, setSelectedKey] = useState<string | null>(null);
|
||||
@@ -149,6 +151,14 @@ export default function KVApp() {
|
||||
onClick={() => setReloadToken((n) => n + 1)}
|
||||
title="refresh tree"
|
||||
>Refresh</button>
|
||||
<button
|
||||
className="kv-btn-icon kv-app-gear"
|
||||
onClick={() => setSnapshotOpen(true)}
|
||||
title="Snapshot — export / import / wipe"
|
||||
aria-label="Open snapshot settings"
|
||||
>
|
||||
⚙
|
||||
</button>
|
||||
</div>
|
||||
<SearchFieldChips fields={searchFields} onChange={setSearchFields} />
|
||||
{breadcrumb && breadcrumb.length > 0 && (
|
||||
@@ -237,6 +247,28 @@ export default function KVApp() {
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{snapshotOpen && (
|
||||
<div
|
||||
className="kv-modal-backdrop"
|
||||
onClick={() => setSnapshotOpen(false)}
|
||||
>
|
||||
<div
|
||||
className="kv-modal"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<button
|
||||
className="kv-modal-close"
|
||||
onClick={() => setSnapshotOpen(false)}
|
||||
aria-label="Close"
|
||||
title="Close"
|
||||
>×</button>
|
||||
<SnapshotPanel />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ToastStack toasts={toasts} onDismiss={dismissToast} />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user