feat: multi SQL tabs, chart suite, Redis engine, perf/memory + UI fixes - #56
Draft
broisnischal wants to merge 30 commits into
Draft
broisnischal wants to merge 30 commits into
broisnischal wants to merge 30 commits into
Conversation
Add a 'New SQL Editor' command to the Cmd-K palette that always opens a fresh SQL editor tab instead of focusing the single existing one. The existing per-tab SqlTabState snapshot swap already keeps each tab's buffer/results isolated, so multiple query editors can now be open and switched between at once. - studio-tabs: createSqlTab accepts an optional title (defaults unchanged) - StudioShell: openNewSqlTab() appends a numbered 'Query Editor N' tab, wired to the new onnewsql palette callback - CommandPalette: new 'New SQL Editor' item (plus icon)
|
…idy tab menu - TableToolbar: replace loud solid-blue (bg-primary) active state on the Aa/ab/.* search toggles with a subtle bg-primary/15 text-primary chip, rounded-md, lighter idle color (DESIGN_SYSTEM §3: no full-primary fill on small controls) - DataTable: pin the inline insert (+Add) row with position:sticky top:HEADER_H instead of an absolute row whose top was recomputed from _physScrollTop every scroll frame — removes the vertical jitter + ghost row and keeps it in lock-step with columns during horizontal scroll - TabBar: relabel 'Reopen Closed Tab' -> 'Reopen last tab' - context-menu-item: add whitespace-nowrap so menu items never wrap to two rows - StudioShell: never evict rows for a tab that is a visible split pane's active tab (would blank it to the 'Focus this pane to load' placeholder)
…orms
macOS was the only platform left on subpixel ('auto'), which renders UI text
noticeably heavier than the design intent. Switch the base html rule to
-webkit-font-smoothing: antialiased / -moz-osx-font-smoothing: grayscale so
macOS matches the crisp, lighter weight already used on Windows/Linux. Leaves
font-synthesis untouched (documented WebKit assertion on Linux startup).
PaneSnapshot always rendered the plain grid, so a split pane showing the chart view reverted to the table when it lost focus. Add a chart branch (dataViewMode === 'chart', which already round-trips through the tab snapshot) that mounts ChartView, mirroring the live view guard in StudioShell.
…-labels - Plain bar charts now sort categories by descending magnitude (ECharts kept arbitrary first-seen order), so a 50-category bar chart reads as a clean ranking. Skipped for timestamp axes (chronological order matters) and for line/area/step (sorting would scramble the connected path). - Truncated categorical x-axis labels now show an ellipsis (…) so cut values (e.g. long emails) are obviously truncated; the full value remains in the axis tooltip.
…earch clear icon - EChartPanel: coalesce ResizeObserver bursts into one chart.resize() per animation frame (pane drags/window resizes fired a synchronous resize on every event, janking the UI) - chart-utils: pie/donut/funnel now aggregate by category (aggPairs) instead of one slice per row — duplicate categories collapsed into a single summed slice, consistent with the bar chart; slices sorted by value desc - ChartView: stop the axis-seed effect from clobbering the user's Category/Value/ Group picks on every column-list change; only re-guess a selector when its current column no longer exists - TableToolbar: align the search clear (x) button with the refined toggles (subtle idle/hover, transition) and size the icon to size-3.5
…tive panes - PaneSnapshot now renders json/record/text/erd (not just chart), each mirroring the live StudioShell guard, so a demoted pane keeps whatever view it was in instead of reverting to the plain grid. Threads connectionId (chart) and schemas (erd) in as new props; replicates dataViewColumns/dataViewRows hidden-column filtering locally. - PaneLayout: remove the bg-background/45 overlay that dimmed inactive split panes — every pane now renders at full brightness (there was no setting for this; it was hardcoded). - studio-tabs: widen TableTabState.dataViewMode union to include chart | erd.
buildOption gains an accent param; it shadows the module palette with the live theme accent as the lead color, so single-series charts and accents follow the app's --primary token instead of a hardcoded indigo. ChartView resolves --primary to rgb() via a probe element (zrender can't parse oklch) and re-resolves on theme change.
…drogram/word-cloud Crash-safety / perf: - Replace Math.max(...arr)/Math.min(...arr) spreads (gauge/bubble/heatmap/radar/ histogram/bullet) with loop-based arrMax/arrMin — spreads throw RangeError past ~100k elements, i.e. exactly the large-result case. - ChartView caps chart input to 50k rows via uniform sampling before the O(n) coercion + buildOption, so ~1M-row results stay responsive; toolbar shows a 'sampled N of M' note. - Wrap buildOption in try/catch and the chart render in <svelte:boundary> with a failed snippet + Retry, so a bad chart shows an inline error instead of crashing the tab/app. Correctness: - Sankey: require a target column, aggregate duplicate source→target pairs (was one link per row → 8k-link hairball), drop reverse edges of 2-cycles (ECharts sankey needs a DAG), cap to 200 links. - Tree/dendrogram: shared buildTreeData — dedup by name, single parent per node, cycle guard, capped node count (old build shared node refs across parents and crashed on cycles). - Word cloud: textStyle.color was an array (invalid → black-on-black in dark theme); now a per-word themed-palette function; aggregate + cap to top 150.
…orizontal scroll - Bar charts hover with a 'shadow' axisPointer (highlights the whole category column — the expected bar hover) instead of the thin crosshair line that made hover feel disconnected. Line/area keep the line pointer. - Harden the --primary accent probe: if the var doesn't resolve to a real color (unset / unparseable in the engine) it silently inherited the foreground, which painted every bar white in the dark theme. Detect that (compare to a control that inherits) and fall back to the default palette. - Value axis ticks use a compact formatter (1200000 -> 1.2M, 3500 -> 3.5k). - bar-horizontal gains a vertical scroll/zoom slider when categories exceed ~25 (the generic dataZoom only covered the horizontal x-axis).
…ALL charts - ConnectionModal: swap the BigQuery provider entry for Redis (coming-soon, disabled), update DRIVER_ORDER + engine tint + guards. - chart-utils: add resolveChartAccent() and resolve it inside buildOption as the default accent, so every chart path — table view, SQL editor, AI charts, chart previews — follows the theme's --primary, not just the table ChartView. Falls back to the default palette when --primary can't resolve. ChartView now shares this resolver (dedup) and keeps re-resolving on theme change.
- Client-side search filters the active object list (tables/views/functions/ triggers) across all string columns; count strip shows 'N of M' while filtering and clears on tab switch. (Ctrl/Cmd+R refresh was already wired.) - Sub-tabs: drop the mono font, add font-medium on the active tab, brighten inactive hover, and swap the 1px underline for a rounded h-0.5 accent bar to match the design-system tab treatment.
…e form Surface the existing (fully working) libSQL/Turso remote driver from the SQLite connection form: a Local file / Remote segmented toggle switches dbType between 'sqlite' and 'libsql', reusing the proven remote backend (no new plumbing). The libSQL form gets the reciprocal toggle back to a local file.
Plain-view rows used a 2-column grid with no count cell, so views never showed the row count that tables and materialized views display — the data pipeline already fetches counts for views. Add the trailing count column (matching the materialized-view row) so 'count' works for views too.
- Toolbar height h-10 -> h-9; title icon size-4 -> size-3.5, drop font-mono from chrome labels (sans for UI text). - Schema + Export triggers/panels use the design-system recipes: border-input bg-input/30 triggers with data-[state=open] accent, popovers rounded-[10px] border-border/60 elevate-2-rim with padded rounded-md items (text-ui-sm, gap-2), no more font-mono/shadow-lg/raw file-type icon colors. - Search input uses the compact input recipe (border-input bg-input/30, size-3.5 leading icon). - Connected toggle uses the canonical prominent-selected recipe (bg-primary/10 text-foreground ring-primary/25) instead of the forbidden /10-vs-/15 mix. - Layout + refresh icon buttons are now both the borderless canonical icon-button (were inconsistently styled); status text /45 -> /60 with tabular-nums.
StudioShell had a literal NUL (\x00) as the separator in tabs.map(t => t.id).join(...), which made git/grep/editors treat the whole file as binary (every search needed rg -a). Replace it with a printable '|' separator — same reactivity-key behaviour, text-clean file.
…scroll lag) The live rows var is $state.raw so draw() can index rows[r][c] per cell per frame without proxy traps. But tabs is a deep-proxied $state, so a rows array stored in a tab and read back on re-activation returned a PROXY, which the canvas then indexed per cell per frame — reintroducing exactly the proxy-trap cost $state.raw exists to avoid (the scroll-lag regression on any revisited table tab). Keep the raw array in a non-reactive Map keyed by tab id and restore that raw reference (not tab.state.rows) when re-activating a cached table tab. Released on eviction and tab close. Additive and reversible — no change to data loading.
- canvas-table withAlpha: nested color->alpha Map so the per-cell cache-hit path allocates nothing (the old color+'@'+a key minted a throwaway string on every call — hundreds of thousands/sec during scroll → GC jank). - StudioShell: cap _tableListCache at 64 entries (was unbounded; grew one entry per connection:schema for the whole session).
…ate-2-rim) context-menu-sub-content and dropdown-menu-sub-content used rounded-xl + shadow-lg /shadow-sm, so every submenu rendered with a different radius and shadow than its parent menu (the inconsistent, unpolished look on the transforms submenu). Align both to the design-system popover recipe used by the parent content (border-border/60, rounded-[10px], elevate-2-rim) so nested menus match app-wide.
Infinite-scroll mode appended every fetched page into _infiniteRows with no ceiling, so scrolling a large table kept the whole result set resident (and deep-proxied) — unbounded memory. Stop auto-loading once 200k rows accumulate. (Kept the array as $state to preserve the in-place-push length signal the grid relies on; the cap bounds the proxy footprint.)
Drop the clear-search X from size-3.5 to size-3 so it sits lighter in the 20px control alongside the Aa/ab/.* toggles.
The Aa / ab / .* toggles read chunky. Shrink the box size-5 -> size-4, the glyph text-ui-2xs -> text-ui-3xs with font-semibold for legibility at the smaller size, and dim idle a touch (/50 -> /45). Keeps the subtle bg-primary/15 active tint.
Replace the ad-hoc 'Aa'/'ab'/'.*' text labels with the proper lucide case-sensitive / whole-word / regex icons, and style the buttons exactly like the clear (x) button — size-5 rounded-md, size-3.5 icon, subtle idle/hover, and the bg-primary/15 text-primary active tint. Consistent, crisp, no more text-glyph chunkiness.
The toggle cluster animated in with transition:fly, whose transform rasterizes its SVG children onto a sub-pixel bitmap — the blurry icons. Switch to an opacity-only fade (no transform) so the case/word/regex icons stay pixel-crisp. Drop the now-unused fly + cubicOut imports.
…blurry) On the app's 14px rem base, size-3.5 = 12.25px — a fractional SVG box, so these detailed case/word/regex icons landed off the pixel grid and rendered blurry. Use integer px: 14px icon centred in an 18px button (2px each side) so strokes align to whole pixels.
…risp 14px read too small; bump to a 16px icon in a 22px button (3px each side). Both integer px so the icons stay on the pixel grid and crisp.
Backend: - add redis 1.4.1 crate; new db/redis.rs driver (open/ping/query raw command -> SqlResult) with SQL-shaped stubs for the shared data contract - RedisConfig + Redis variant on AnyConnectionConfig/ActiveConnection + driver(); connect_redis/test_redis_connection; test_redis/connect_redis_db commands + lib.rs registration - Redis arms added to every exhaustive match (query.rs, schema.rs, backup.rs, mcp/tools.rs) — SQL-only ops return a clean 'not supported' / empty; execute_sql routes raw commands to redis::query Frontend: - Redis selectable in the connection modal with host/port/password/DB-index/TLS form; api.js testRedis/connectRedis; DbType + SavedConnection + db-capabilities (kept out of SQL feature sets; added isKeyValue helper) cargo check + npm run build both clean.
…y gating - RedisKeyspacePage.svelte: left key list (grouped by ':' prefix, filter, count), right per-type value viewer (string/hash/list/set/zset + TTL + type chip), and a bottom redis-cli console (history, scrollback, auto-refresh after writes). Runs entirely on the executeSql->redis::query routing. - studio-tabs: 'redis' tab kind + createRedisTab/findRedisTab + tabDisplayTitle. - StudioShell: isRedis capability; onConnected (and auto-reconnect/connectByType/ switch-db) skip the relational catalog load and open the Redis tab; keep-alive render of RedisKeyspacePage; hide the tables sidebar for redis; gate SQL-only welcome-grid cells + command-palette items behind !isRedis; add a Redis connect branch to auto-reconnect/connectByType. - CommandPalette: isRedis/onopenredis props; SQL pages gated, 'Redis Keyspace' item. - StatusBar: show 'Redis' (was falling through to 'PostgreSQL') + a 'db N' indicator.
The console pushed a plain object into the $state scrollback then mutated it in
place — bypassing the proxy, so replies never rendered ('cli not working').
Replace the entry immutably once the reply lands. Add redis-cli-style formatting
((nil), (integer) N, quoted strings, numbered arrays, (error) …) and handle
'clear' locally like a terminal.
- Per-key TYPE badges in the tree (string/hash/list/set/zset/stream, color-coded lucide glyphs; types fetched concurrently, capped at 500). - Value panel: key toolbar (copy key, delete-with-confirm, TTL chip, size, reload); string viewer with JSON/Raw toggle + copy; hash/zset/list/set as clean sticky-header 2-col tables with per-row copy. - Chrome: 'Keys' header + count, compact filter input recipe, canonical bg-primary/10 selection, group chevrons; refined redis-cli console styling. - All key interpolations quoted via quoteArg; loaders gated on active+redis.
broisnischal
force-pushed
the
feat/ui-design-system-revamp
branch
from
July 22, 2026 04:07
0ac32a9 to
a2da516
Compare
broisnischal
force-pushed
the
feat/ui-design-system-revamp
branch
from
August 8, 2026 04:32
a2da516 to
d311a8f
Compare
broisnischal
force-pushed
the
feat/multi-sql-tabs
branch
from
August 8, 2026 04:32
efd0eea to
86c1294
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Large multi-area branch (30 commits). Base:
feat/ui-design-system-revamp.SQL editor
Split panes
Charts
Performance / memory
Redis engine (new, end-to-end)
UI / design-system fixes