pi-studio 0.6.1 → 0.6.3

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `pi-studio` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.6.3] — 2026-04-29
8
+
9
+ ### Changed
10
+ - Polished rendered code blocks so ordinary code text uses normal foreground, Python function definitions keep function-name highlighting, and fenced-block borders are softened to better match theme intent.
11
+ - Slightly sharpened footer metadata and shortcut text for better readability across darker custom themes.
12
+
13
+ ## [0.6.2] — 2026-04-29
14
+
15
+ ### Changed
16
+ - Polished refreshed Studio theme surfaces so light-mode header actions, scratchpad panels, response-history badges, and editor surfaces are more consistent.
17
+ - Softened overly sharp derived borders in high-contrast themes while preserving theme hue and tightened secondary info text contrast in comment, outline, and scratchpad panels.
18
+
7
19
  ## [0.6.1] — 2026-04-29
8
20
 
9
21
  ### Added
package/client/studio.css CHANGED
@@ -1143,7 +1143,7 @@
1143
1143
  }
1144
1144
 
1145
1145
  .rendered-markdown pre code {
1146
- color: var(--md-codeblock);
1146
+ color: var(--text);
1147
1147
  white-space: inherit;
1148
1148
  }
1149
1149
 
@@ -1846,7 +1846,7 @@
1846
1846
  footer {
1847
1847
  border-top: 1px solid var(--panel-border);
1848
1848
  padding: 8px 12px;
1849
- color: var(--muted);
1849
+ color: var(--studio-footer-text, var(--muted));
1850
1850
  font-size: 12px;
1851
1851
  min-height: 32px;
1852
1852
  background: var(--panel);
@@ -1903,7 +1903,7 @@
1903
1903
  .footer-meta {
1904
1904
  grid-area: meta;
1905
1905
  justify-self: start;
1906
- color: var(--muted);
1906
+ color: var(--studio-footer-text, var(--muted));
1907
1907
  font-size: 11px;
1908
1908
  text-align: left;
1909
1909
  max-width: 100%;
@@ -1954,12 +1954,12 @@
1954
1954
  grid-area: hint;
1955
1955
  justify-self: end;
1956
1956
  align-self: center;
1957
- color: var(--muted);
1957
+ color: var(--studio-footer-text, var(--muted));
1958
1958
  font-size: 11px;
1959
1959
  white-space: nowrap;
1960
1960
  text-align: right;
1961
1961
  font-style: normal;
1962
- opacity: 0.9;
1962
+ opacity: 0.86;
1963
1963
  display: inline-flex;
1964
1964
  align-items: center;
1965
1965
  gap: 8px;
@@ -2020,7 +2020,7 @@
2020
2020
  gap: 12px;
2021
2021
  padding: 16px 18px 12px;
2022
2022
  border-bottom: 1px solid var(--panel-border);
2023
- background: var(--panel-2);
2023
+ background: var(--scratchpad-header-bg, var(--panel-2));
2024
2024
  }
2025
2025
 
2026
2026
  .scratchpad-header > div {
@@ -2038,7 +2038,7 @@
2038
2038
  margin: 6px 0 0;
2039
2039
  font-size: 12px;
2040
2040
  line-height: 1.45;
2041
- color: var(--muted);
2041
+ color: var(--studio-info-text, var(--muted));
2042
2042
  max-width: none;
2043
2043
  }
2044
2044
 
@@ -2057,7 +2057,7 @@
2057
2057
  border-radius: 0;
2058
2058
  margin: 0;
2059
2059
  padding: 16px 18px;
2060
- background: var(--panel);
2060
+ background: var(--scratchpad-body-bg, var(--panel));
2061
2061
  color: var(--text);
2062
2062
  font-family: var(--font-mono);
2063
2063
  font-size: 13px;
@@ -2073,12 +2073,12 @@
2073
2073
  gap: 12px;
2074
2074
  flex-wrap: wrap;
2075
2075
  padding: 12px 18px 16px;
2076
- background: var(--panel);
2076
+ background: var(--scratchpad-body-bg, var(--panel));
2077
2077
  }
2078
2078
 
2079
2079
  .scratchpad-meta {
2080
2080
  font-size: 12px;
2081
- color: var(--muted);
2081
+ color: var(--studio-info-text, var(--muted));
2082
2082
  }
2083
2083
 
2084
2084
  .scratchpad-actions {
@@ -2140,7 +2140,7 @@
2140
2140
  padding: 14px;
2141
2141
  font-size: 13px;
2142
2142
  line-height: 1.5;
2143
- color: var(--muted);
2143
+ color: var(--studio-info-text, var(--muted));
2144
2144
  border-bottom: 1px solid var(--panel-border);
2145
2145
  background: var(--panel);
2146
2146
  }
@@ -2229,7 +2229,7 @@
2229
2229
 
2230
2230
  .outline-entry-meta {
2231
2231
  font-size: 11px;
2232
- color: var(--muted);
2232
+ color: var(--studio-info-text, var(--muted));
2233
2233
  white-space: nowrap;
2234
2234
  font-variant-numeric: tabular-nums;
2235
2235
  }
@@ -2553,7 +2553,7 @@
2553
2553
  body.studio-ui-refresh #rightSectionHeader button:not(:disabled):hover,
2554
2554
  body.studio-ui-refresh .studio-refresh-toolbar button:not(:disabled):hover,
2555
2555
  body.studio-ui-refresh .studio-refresh-toolbar select:not(:disabled):hover {
2556
- background: var(--panel-2);
2556
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
2557
2557
  }
2558
2558
 
2559
2559
  body.studio-ui-refresh #leftSectionHeader #editorViewSelect,
@@ -2653,10 +2653,18 @@
2653
2653
  border-radius: 8px;
2654
2654
  }
2655
2655
 
2656
+ body.studio-ui-refresh #reviewNotesBtn,
2657
+ body.studio-ui-refresh #outlineBtn,
2658
+ body.studio-ui-refresh #scratchpadBtn,
2659
+ body.studio-ui-refresh .studio-refresh-tool-tab {
2660
+ background: var(--studio-header-action-bg, transparent);
2661
+ border-color: var(--studio-header-action-border, transparent);
2662
+ }
2663
+
2656
2664
  body.studio-ui-refresh #exportPdfBtn {
2657
- background: var(--panel-2);
2665
+ background: var(--studio-header-filled-bg, var(--panel-2));
2658
2666
  color: var(--text);
2659
- border-color: transparent;
2667
+ border-color: var(--studio-header-action-border, transparent);
2660
2668
  }
2661
2669
 
2662
2670
  body.studio-ui-refresh #reviewNotesBtn.is-active,
@@ -2834,7 +2842,7 @@
2834
2842
 
2835
2843
  body.studio-ui-refresh .studio-refresh-chip.is-open,
2836
2844
  body.studio-ui-refresh .studio-refresh-chip:hover {
2837
- background: var(--panel-2);
2845
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
2838
2846
  color: var(--text);
2839
2847
  }
2840
2848
 
@@ -2917,7 +2925,7 @@
2917
2925
 
2918
2926
  body.studio-ui-refresh .studio-refresh-menu-item > button:not(:disabled):hover,
2919
2927
  body.studio-ui-refresh .studio-refresh-menu-item > select:not(:disabled):hover {
2920
- background: var(--panel-2);
2928
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
2921
2929
  }
2922
2930
 
2923
2931
  body.studio-ui-refresh #copyDraftBtn:only-child {
package/index.ts CHANGED
@@ -864,6 +864,26 @@ function readableTextOn(background: string, darkText = "#0e1616", lightText = "#
864
864
  return contrastRatio(background, darkText) >= contrastRatio(background, lightText) ? darkText : lightText;
865
865
  }
866
866
 
867
+ function capBorderContrast(color: string, surface: string, maxContrast: number): string {
868
+ if (!hexToRgb(color) || !hexToRgb(surface)) return color;
869
+ if (contrastRatio(color, surface) <= maxContrast) return color;
870
+
871
+ let low = 0;
872
+ let high = 1;
873
+ let result = color;
874
+ for (let i = 0; i < 12; i += 1) {
875
+ const mid = (low + high) / 2;
876
+ const candidate = blendColors(color, surface, mid);
877
+ if (contrastRatio(candidate, surface) > maxContrast) {
878
+ low = mid;
879
+ } else {
880
+ result = candidate;
881
+ high = mid;
882
+ }
883
+ }
884
+ return result;
885
+ }
886
+
867
887
  function deriveCanvasColors(
868
888
  baseColor: string,
869
889
  mode: StudioThemeMode,
@@ -4321,6 +4341,13 @@ async function writeStudioSystemClipboard(text: string): Promise<{ ok: true; met
4321
4341
  return { ok: false, error: errors.join("; ") || "No system clipboard command is available." };
4322
4342
  }
4323
4343
 
4344
+ function decorateStudioPandocSyntaxHtml(html: string): string {
4345
+ return html.replace(
4346
+ /(<span class="kw">def<\/span>)(\s*)([A-Za-z_][A-Za-z0-9_]*)(?=\s*\()/g,
4347
+ (_match, keyword: string, spacing: string, name: string) => `${keyword}${spacing}<span class="fu">${name}</span>`,
4348
+ );
4349
+ }
4350
+
4324
4351
  async function renderStudioMarkdownWithPandoc(markdown: string, isLatex?: boolean, resourcePath?: string, sourcePath?: string): Promise<string> {
4325
4352
  const pandocCommand = process.env.PANDOC_PATH?.trim() || "pandoc";
4326
4353
  const markdownWithoutHtmlComments = isLatex ? markdown : stripStudioMarkdownHtmlComments(markdown);
@@ -4401,6 +4428,7 @@ async function renderStudioMarkdownWithPandoc(markdown: string, isLatex?: boolea
4401
4428
  } else {
4402
4429
  html = decorateStudioPreviewPageBreakHtml(html);
4403
4430
  }
4431
+ html = decorateStudioPandocSyntaxHtml(html);
4404
4432
  succeed(stripMathMlAnnotationTags(html));
4405
4433
  return;
4406
4434
  }
@@ -6165,10 +6193,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
6165
6193
  style.mode === "light"
6166
6194
  ? `0 1px 2px ${withAlpha(style.palette.text, 0.035, "rgba(15, 23, 42, 0.03)")}, 0 4px 14px ${withAlpha(style.palette.text, 0.055, "rgba(15, 23, 42, 0.04)")}`
6167
6195
  : "0 1px 2px rgba(0, 0, 0, 0.30), 0 6px 18px rgba(0, 0, 0, 0.18)";
6168
- const borderSubtle = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.58 : 0.48);
6169
- const panelBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.42 : 0.36);
6170
- const controlBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.30 : 0.22);
6171
- const paneActiveBorder = blendColors(style.palette.border, style.palette.panel, style.mode === "light" ? 0.34 : 0.48);
6196
+ const rawBorderSubtle = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.58 : 0.48);
6197
+ const rawPanelBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.42 : 0.36);
6198
+ const rawControlBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.30 : 0.22);
6199
+ const rawPaneActiveBorder = blendColors(style.palette.border, style.palette.panel, style.mode === "light" ? 0.34 : 0.48);
6200
+ const borderSubtle = capBorderContrast(rawBorderSubtle, style.palette.panel, style.mode === "light" ? 1.10 : 1.12);
6201
+ const panelBorder = capBorderContrast(rawPanelBorder, style.palette.panel, style.mode === "light" ? 1.15 : 1.18);
6202
+ const controlBorder = capBorderContrast(rawControlBorder, style.palette.panel, style.mode === "light" ? 1.22 : 1.25);
6203
+ const paneActiveBorder = capBorderContrast(rawPaneActiveBorder, style.palette.panel, style.mode === "light" ? 1.38 : 1.45);
6172
6204
  const accentContrast = style.accentContrast ?? (style.mode === "light" ? "#ffffff" : "#0e1616");
6173
6205
  const errorContrast = style.errorContrast ?? readableTextOn(style.palette.error);
6174
6206
  const blockquoteBg = withAlpha(
@@ -6186,6 +6218,8 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
6186
6218
  style.mode === "light" ? 0.13 : 0.18,
6187
6219
  style.mode === "light" ? "rgba(15, 23, 42, 0.06)" : "rgba(255, 255, 255, 0.07)",
6188
6220
  );
6221
+ const rawCodeBlockBorder = blendColors(style.palette.mdCodeBlockBorder, style.palette.panel2, style.mode === "light" ? 0.62 : 0.72);
6222
+ const codeBlockBorder = capBorderContrast(rawCodeBlockBorder, style.palette.panel2, style.mode === "light" ? 1.16 : 1.18);
6189
6223
  const diffAddedBg = withAlpha(style.palette.ok, style.mode === "light" ? 0.10 : 0.14, "rgba(46, 160, 67, 0.12)");
6190
6224
  const diffRemovedBg = withAlpha(style.palette.error, style.mode === "light" ? 0.10 : 0.14, "rgba(248, 81, 73, 0.12)");
6191
6225
  const okSoft = withAlpha(style.palette.ok, style.mode === "light" ? 0.10 : 0.12, "rgba(115, 209, 61, 0.08)");
@@ -6201,6 +6235,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
6201
6235
  const editorGutterBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
6202
6236
  const referenceMetaBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
6203
6237
  const referenceBadgeBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel;
6238
+ const scratchpadHeaderBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
6239
+ const scratchpadBodyBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel;
6240
+ const infoText = blendColors(style.palette.text, style.palette.muted, style.mode === "light" ? 0.36 : 0.30);
6241
+ const footerText = blendColors(style.palette.text, style.palette.muted, style.mode === "light" ? 0.50 : 0.42);
6242
+ const headerActionBg = style.mode === "light" ? lightPrimarySurface : "transparent";
6243
+ const headerActionHoverBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel2;
6244
+ const headerActionBorder = style.mode === "light" ? controlBorder : "transparent";
6245
+ const headerFilledBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel2;
6204
6246
  const monoFontStack = getStudioMonoFontStack();
6205
6247
  const uiFontStack = getStudioUiFontStack();
6206
6248
  const proseFontStack = getStudioProseFontStack();
@@ -6233,7 +6275,7 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
6233
6275
  "--md-link-url": style.palette.mdLinkUrl,
6234
6276
  "--md-code": style.palette.mdCode,
6235
6277
  "--md-codeblock": style.palette.mdCodeBlock,
6236
- "--md-codeblock-border": style.palette.mdCodeBlockBorder,
6278
+ "--md-codeblock-border": codeBlockBorder,
6237
6279
  "--md-quote": style.palette.mdQuote,
6238
6280
  "--md-quote-border": style.palette.mdQuoteBorder,
6239
6281
  "--md-hr": style.palette.mdHr,
@@ -6264,6 +6306,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
6264
6306
  "--editor-gutter-bg": editorGutterBg,
6265
6307
  "--reference-meta-bg": referenceMetaBg,
6266
6308
  "--reference-badge-bg": referenceBadgeBg,
6309
+ "--scratchpad-header-bg": scratchpadHeaderBg,
6310
+ "--scratchpad-body-bg": scratchpadBodyBg,
6311
+ "--studio-info-text": infoText,
6312
+ "--studio-footer-text": footerText,
6313
+ "--studio-header-action-bg": headerActionBg,
6314
+ "--studio-header-action-hover-bg": headerActionHoverBg,
6315
+ "--studio-header-action-border": headerActionBorder,
6316
+ "--studio-header-filled-bg": headerFilledBg,
6267
6317
  "--font-ui": uiFontStack,
6268
6318
  "--font-prose": proseFontStack,
6269
6319
  "--font-mono": monoFontStack,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-studio",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, prompt/response history, and live Markdown/LaTeX/code preview",
5
5
  "type": "module",
6
6
  "license": "MIT",