ACloudCenter Claude Fable 5 commited on
Commit
88f088c
·
1 Parent(s): a4d6323

Fix cursor flicker from a resizing modal; retire the bundled examples

Browse files

The stage was a vertically centred dialog whose content changes every
second, so each height delta moved ALL of its content by half — which
reads as the pointer flashing between hand and arrow as buttons slide
under it. The dialog is now anchored near the top so growth only
extends downward, the log and text rows have reserved heights, and the
progress bar is always present (sweeping during warm-up) instead of
toggling hidden and shifting everything by 22px. Verified: no
cursor-flapping points across a 680x760 grid over a full lifecycle.

Examples: the bundled scripts predate the current app, so they no
longer load; the chip row hides itself and the empty-state copy points
at Write with AI and import instead. Loader and files are left intact
behind a flag for a future curated set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Files changed (4) hide show
  1. app.py +5 -1
  2. static/app.js +12 -5
  3. static/index.html +2 -2
  4. static/styles.css +9 -1
app.py CHANGED
@@ -455,7 +455,11 @@ def _build_examples_index() -> list[dict]:
455
  return index
456
 
457
 
458
- EXAMPLES_INDEX = _build_examples_index()
 
 
 
 
459
 
460
 
461
  # --- Modal Connection ---
 
455
  return index
456
 
457
 
458
+ # Examples retired 2026-08-22 (Josh) — the bundled scripts predate the current
459
+ # app and no longer fit it. The loader and text_examples/ files are left intact
460
+ # so restoring a curated set is a one-line change.
461
+ SHOW_BUNDLED_EXAMPLES = False
462
+ EXAMPLES_INDEX = _build_examples_index() if SHOW_BUNDLED_EXAMPLES else []
463
 
464
 
465
  # --- Modal Connection ---
static/app.js CHANGED
@@ -1061,7 +1061,7 @@ function renderTurns() {
1061
  empty.id = "emptyTurns";
1062
  empty.innerHTML =
1063
  '<div class="empty-title">No scene yet</div>' +
1064
- "Type a scenario above and click <strong>Write with AI</strong>, pick an example, or start typing your own line below.";
1065
  el.turnsList.append(empty);
1066
  updateMeta();
1067
  return;
@@ -1170,6 +1170,7 @@ function loadScriptResult(result, titleFallback, summary) {
1170
  /* ---------------- Examples ---------------- */
1171
  function renderExamplePills() {
1172
  el.examplePills.innerHTML = "";
 
1173
  state.examples.forEach((example) => {
1174
  const btn = document.createElement("button");
1175
  btn.type = "button";
@@ -1703,7 +1704,12 @@ function paintProgress() {
1703
  let pctText = "Starting…";
1704
  if (!progress.genStartedAt) {
1705
  // Still warming up — say so plainly instead of ticking a generation clock.
 
1706
  el.progressMeta.hidden = false;
 
 
 
 
1707
  const warm = `GPU warming up · ${formatMinutes(elapsed) || "0s"}`;
1708
  el.progressMeta.textContent = warm;
1709
  el.genStagePct.textContent = "Warming up…";
@@ -1768,7 +1774,8 @@ function showStagePane(which) {
1768
  function openGenerateStage(title) {
1769
  el.genStageTitle.textContent = (title || "Untitled conversation").toUpperCase();
1770
  el.genStagePct.textContent = "Starting…";
1771
- el.genStageTrack.hidden = true;
 
1772
  el.genStageFill.style.width = "0%";
1773
  el.genStageLog.textContent = "";
1774
  showStagePane("generating");
@@ -1789,9 +1796,9 @@ function startProgress() {
1789
  progress.genStartedAt = 0;
1790
  progress.warmupSecs = 0;
1791
  el.progressFill.style.width = "0%";
1792
- el.progressTrack.classList.remove("indeterminate");
1793
- el.genStageTrack.classList.remove("indeterminate");
1794
- el.progressTrack.hidden = true;
1795
  clearInterval(progress.ticker);
1796
  progress.ticker = setInterval(paintProgress, 1000);
1797
  paintProgress();
 
1061
  empty.id = "emptyTurns";
1062
  empty.innerHTML =
1063
  '<div class="empty-title">No scene yet</div>' +
1064
+ "Describe a scenario above and click <strong>Write with AI</strong>, import a script, or start typing your own line below.";
1065
  el.turnsList.append(empty);
1066
  updateMeta();
1067
  return;
 
1170
  /* ---------------- Examples ---------------- */
1171
  function renderExamplePills() {
1172
  el.examplePills.innerHTML = "";
1173
+ el.examplePills.hidden = !state.examples.length; // no empty gap when unset
1174
  state.examples.forEach((example) => {
1175
  const btn = document.createElement("button");
1176
  btn.type = "button";
 
1704
  let pctText = "Starting…";
1705
  if (!progress.genStartedAt) {
1706
  // Still warming up — say so plainly instead of ticking a generation clock.
1707
+ // The bar stays present and sweeping: hiding it would resize the dialog.
1708
  el.progressMeta.hidden = false;
1709
+ el.progressTrack.hidden = false;
1710
+ el.genStageTrack.hidden = false;
1711
+ el.progressTrack.classList.add("indeterminate");
1712
+ el.genStageTrack.classList.add("indeterminate");
1713
  const warm = `GPU warming up · ${formatMinutes(elapsed) || "0s"}`;
1714
  el.progressMeta.textContent = warm;
1715
  el.genStagePct.textContent = "Warming up…";
 
1774
  function openGenerateStage(title) {
1775
  el.genStageTitle.textContent = (title || "Untitled conversation").toUpperCase();
1776
  el.genStagePct.textContent = "Starting…";
1777
+ el.genStageTrack.hidden = false;
1778
+ el.genStageTrack.classList.add("indeterminate");
1779
  el.genStageFill.style.width = "0%";
1780
  el.genStageLog.textContent = "";
1781
  showStagePane("generating");
 
1796
  progress.genStartedAt = 0;
1797
  progress.warmupSecs = 0;
1798
  el.progressFill.style.width = "0%";
1799
+ el.progressTrack.classList.add("indeterminate");
1800
+ el.genStageTrack.classList.add("indeterminate");
1801
+ el.progressTrack.hidden = false;
1802
  clearInterval(progress.ticker);
1803
  progress.ticker = setInterval(paintProgress, 1000);
1804
  paintProgress();
static/index.html CHANGED
@@ -129,8 +129,8 @@
129
  <div id="turnsList">
130
  <div class="empty-transcript" id="emptyTurns">
131
  <div class="empty-title">No scene yet</div>
132
- Type a scenario above and click <strong>Write with AI</strong>, pick an example, or
133
- start typing your own line below.
134
  </div>
135
  </div>
136
  <button class="add-turn" id="addTurnBtn" type="button">+ Add a line</button>
 
129
  <div id="turnsList">
130
  <div class="empty-transcript" id="emptyTurns">
131
  <div class="empty-title">No scene yet</div>
132
+ Describe a scenario above and click <strong>Write with AI</strong>, import a script,
133
+ or start typing your own line below.
134
  </div>
135
  </div>
136
  <button class="add-turn" id="addTurnBtn" type="button">+ Add a line</button>
static/styles.css CHANGED
@@ -845,6 +845,11 @@ dialog::backdrop { background: rgba(42, 32, 22, 0.45); }
845
  border-radius: 24px;
846
  max-height: 90vh;
847
  overflow-y: auto;
 
 
 
 
 
848
  }
849
  .player-stage::backdrop { background: rgba(42, 32, 22, 0.55); }
850
  .stage-body { padding: 36px 36px 30px; }
@@ -889,20 +894,23 @@ body.is-generating .canvas { opacity: 0.6; transition: opacity 0.2s; }
889
  font-variant-numeric: tabular-nums;
890
  }
891
  .gen-track { height: 10px; margin-bottom: 12px; }
 
892
  .gen-stage-meta {
893
  text-align: center;
894
  font-size: 0.9rem;
895
  font-weight: 700;
896
  color: var(--ink);
897
  font-variant-numeric: tabular-nums;
 
898
  }
899
  .gen-stage-desc {
900
  text-align: center;
901
  font-size: 0.84rem;
902
  color: var(--ink-faint);
903
  margin-top: 6px;
904
- min-height: 1.2em;
905
  }
 
906
  .gen-stage-log {
907
  margin-top: 18px;
908
  background: var(--paper-soft);
 
845
  border-radius: 24px;
846
  max-height: 90vh;
847
  overflow-y: auto;
848
+ /* Anchored near the top rather than centred: the generating view changes
849
+ height every second, and a centred dialog would shift ALL its content by
850
+ half of every delta — which reads as the pointer flickering. */
851
+ margin-top: 5vh;
852
+ margin-bottom: auto;
853
  }
854
  .player-stage::backdrop { background: rgba(42, 32, 22, 0.55); }
855
  .stage-body { padding: 36px 36px 30px; }
 
894
  font-variant-numeric: tabular-nums;
895
  }
896
  .gen-track { height: 10px; margin-bottom: 12px; }
897
+ /* Fixed heights so per-second text changes can't resize the dialog. */
898
  .gen-stage-meta {
899
  text-align: center;
900
  font-size: 0.9rem;
901
  font-weight: 700;
902
  color: var(--ink);
903
  font-variant-numeric: tabular-nums;
904
+ min-height: 1.4em;
905
  }
906
  .gen-stage-desc {
907
  text-align: center;
908
  font-size: 0.84rem;
909
  color: var(--ink-faint);
910
  margin-top: 6px;
911
+ min-height: 2.6em;
912
  }
913
+ .gen-stage-log { height: 260px; }
914
  .gen-stage-log {
915
  margin-top: 18px;
916
  background: var(--paper-soft);