Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
{"id":"ts-ast-parser-eval-5xj","title":"Fix misc code quality errors","description":"Includes: nested template literals, nested ternary, dead stores, no-case-declarations, prefer-read-only-props, no-array-index-key, dangerouslySetInnerHTML, no-await-in-loop, no-unnecessary-condition, react-refresh warnings","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-19T12:41:55.908368Z","updated_at":"2025-12-19T16:02:24.299207Z","closed_at":"2025-12-19T16:02:24.299207Z","close_reason":"Fixed all misc errors: nested ternaries, array-index-key, dangerouslySetInnerHTML, react-refresh"}
{"id":"ts-ast-parser-eval-63y","title":"Fix prefer-regexp-exec in callStack.ts","description":"Use RegExp.exec() instead of String.match() at line 46","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T12:47:47.385612Z","updated_at":"2025-12-19T14:42:23.252456Z","closed_at":"2025-12-19T14:42:23.252456Z","close_reason":"Validated - no errors remain","dependencies":[{"issue_id":"ts-ast-parser-eval-63y","depends_on_id":"ts-ast-parser-eval-5pa","type":"parent-child","created_at":"2025-12-19T12:48:04.547044Z","created_by":"daemon"}]}
{"id":"ts-ast-parser-eval-664","title":"Fix react-hooks/exhaustive-deps in App.tsx","description":"Add missing dependency playback.currentStep to useMemo at line 83","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T12:48:30.096961Z","updated_at":"2025-12-19T15:04:53.976433Z","closed_at":"2025-12-19T15:04:53.976433Z","close_reason":"Added playback.currentStep to deps","dependencies":[{"issue_id":"ts-ast-parser-eval-664","depends_on_id":"ts-ast-parser-eval-6u6","type":"parent-child","created_at":"2025-12-19T12:48:50.40874Z","created_by":"daemon"}]}
{"id":"ts-ast-parser-eval-66k","title":"Find and consolidate duplicate CSS color declarations","description":"Scan styles.css for duplicate color hex values that can be replaced with existing CSS variables","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T18:16:53.148872Z","updated_at":"2025-12-30T18:24:06.188791Z","closed_at":"2025-12-30T18:24:06.188791Z","close_reason":"All duplicate hardcoded rgba values consolidated to CSS variables"}
{"id":"ts-ast-parser-eval-68y","title":"Fix StepDetailsPanel.tsx hasResult logic bug - line 121 inverted condition","description":"**File:** src/web/components/StepDetailsPanel.tsx:121-122\n\n**Problem:** The `hasResult` condition is inverted. Current logic:\n```typescript\nconst hasResult = step.result !== undefined \u0026\u0026 !step.result;\n```\nThis shows the result bar only when `result` is falsy (empty string, 0, false), which is backwards.\n\n**Expected:** Should show result bar when `step.result` exists and is truthy.\n\n**Fix options:**\n1. `const hasResult = step.result !== undefined \u0026\u0026 step.result !== null;` (show when defined)\n2. `const hasResult = !!step.result;` (show when truthy)\n3. `const hasResult = step.result !== undefined;` (show when not undefined)\n\n**Test failures:**\n- StepDetailsPanel.integration.test.tsx:708 - `expect(screen.getByText(/finalResult/)).toBeDefined()` fails because result bar isn't rendered\n- Related screenshot tests fail due to missing result bar","acceptance_criteria":"- [ ] Result bar displays when step.result has a value\n- [ ] Test `shows Result bar at bottom when result exists` passes\n- [ ] Test `handles union stepping with full data flow` passes\n- [ ] Screenshot tests match expected output","status":"closed","priority":1,"issue_type":"bug","assignee":"claude","created_at":"2025-12-19T16:07:46.785117Z","updated_at":"2025-12-19T16:10:57.849309Z","closed_at":"2025-12-19T16:10:57.849309Z","close_reason":"Fixed hasResult logic on line 121. Also fixed test regex for CallStackSection (`:5` -\u003e `: 5`). All 158 tests now passing."}
{"id":"ts-ast-parser-eval-6b7","title":"Fix @typescript-eslint/await-thenable errors","description":"9 unnecessary awaits on non-Promise values.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-19T12:41:36.374309Z","updated_at":"2025-12-19T14:50:18.227252Z","closed_at":"2025-12-19T14:50:18.227252Z","close_reason":"Removed 9 unnecessary awaits - validated lint passes"}
{"id":"ts-ast-parser-eval-6ip","title":"Fix jsx-a11y in Toast.tsx","description":"Fix click-events-have-key-events and no-static-element-interactions at line 37","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T12:48:29.360676Z","updated_at":"2025-12-19T15:51:06.051816Z","closed_at":"2025-12-19T15:51:06.051816Z","close_reason":"Converted div to button with reset styles","dependencies":[{"issue_id":"ts-ast-parser-eval-6ip","depends_on_id":"ts-ast-parser-eval-d7z","type":"parent-child","created_at":"2025-12-19T12:48:50.084274Z","created_by":"daemon"}]}
Expand Down Expand Up @@ -92,6 +93,7 @@
{"id":"ts-ast-parser-eval-d17","title":"Highlight selected example on landing page","description":"When user clicks an example button on the landing page, visually highlight which example is currently selected","design":"Track selected example in state, apply CSS class to selected button","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T19:41:36.943968Z","updated_at":"2025-12-23T19:44:48.467987Z","closed_at":"2025-12-23T19:44:48.467987Z","close_reason":"Added selectedExample state and .selected CSS class to highlight active example button"}
{"id":"ts-ast-parser-eval-d7z","title":"Fix jsx-a11y accessibility errors","description":"5 accessibility issues - missing keyboard listeners and interactive element roles.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-19T12:41:36.477804Z","updated_at":"2025-12-19T15:51:05.562816Z","closed_at":"2025-12-19T15:51:05.562816Z","close_reason":"Fixed 5 a11y errors: semantic buttons + role=separator"}
{"id":"ts-ast-parser-eval-deu","title":"Fix @eslint-react/dom/no-missing-button-type errors","description":"8 buttons missing type attribute. Need to add type=\"button\".","design":"Add type=\\\"button\\\" to all non-submit buttons","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-19T12:41:36.175215Z","updated_at":"2025-12-19T14:35:13.347946Z","closed_at":"2025-12-19T14:35:13.347946Z","close_reason":"All 7 no-missing-button-type errors fixed"}
{"id":"ts-ast-parser-eval-dfw","title":"Commit CSS variable consolidation changes","description":"Commit the CSS changes that consolidated hardcoded values into CSS variables","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T18:16:53.011456Z","updated_at":"2025-12-30T18:17:46.180412Z","closed_at":"2025-12-30T18:17:46.180412Z","close_reason":"Committed CSS variable consolidation changes (263a998)"}
{"id":"ts-ast-parser-eval-e0h","title":"Exclude lib-bundle.ts from max-len rule","description":"Generated file has 12 lines over 400 chars. Add eslint-disable or update config to ignore.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-19T12:49:11.848848Z","updated_at":"2025-12-23T10:56:21.878107Z","closed_at":"2025-12-23T10:56:21.878107Z","close_reason":"Completed","dependencies":[{"issue_id":"ts-ast-parser-eval-e0h","depends_on_id":"ts-ast-parser-eval-idu","type":"parent-child","created_at":"2025-12-19T12:49:26.629599Z","created_by":"daemon"}]}
{"id":"ts-ast-parser-eval-e7g","title":"Fix slow-regex in traceProcessor.ts","description":"Fix regex vulnerable to super-linear runtime at line 322","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T12:47:14.344472Z","updated_at":"2025-12-19T14:28:47.461299Z","closed_at":"2025-12-19T14:28:47.461299Z","close_reason":"Skipped per user request","dependencies":[{"issue_id":"ts-ast-parser-eval-e7g","depends_on_id":"ts-ast-parser-eval-1c7","type":"parent-child","created_at":"2025-12-19T12:47:27.480309Z","created_by":"daemon"}]}
{"id":"ts-ast-parser-eval-efh","title":"Fix jsx-no-bind: PlaybackControls.test.tsx:9-11","description":"Move arrow functions to variables at lines 9,10,11","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T17:16:06.55211Z","updated_at":"2025-12-19T17:35:04.724203Z","closed_at":"2025-12-19T17:35:04.724203Z","close_reason":"Fixed","dependencies":[{"issue_id":"ts-ast-parser-eval-efh","depends_on_id":"ts-ast-parser-eval-4i7","type":"parent-child","created_at":"2025-12-19T17:16:23.783374Z","created_by":"daemon"}]}
Expand Down
5 changes: 4 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@
"mcp__plugin_beads_beads__set_context",
"mcp__plugin_beads_beads__create",
"mcp__plugin_beads_beads__update",
"mcp__plugin_beads_beads__close"
"mcp__plugin_beads_beads__close",
"Bash(gh pr view:*)",
"Bash(gh pr diff:*)",
"Bash(gh api:*)"
],
"deny": [],
"ask": []
Expand Down
62 changes: 42 additions & 20 deletions src/web/components/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Editor } from "@monaco-editor/react";
import React, { useState, useCallback, useRef } from "react";
import React, { useState, useCallback, useRef, useEffect } from "react";
import { useTheme } from "../hooks/useThemeHook.ts";
import { ThemeDropdown } from "./ThemeDropdown.tsx";

Expand Down Expand Up @@ -120,6 +120,21 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onTryIt }) => {
setInputCode(value ?? "");
}, []);

// Scroll-to-top button visibility
const [ showScrollTop, setShowScrollTop ] = useState(false);

useEffect(() => {
const handleScroll = () => {
setShowScrollTop(window.scrollY > 200);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);

const scrollToTry = useCallback(() => {
document.getElementById("try")?.scrollIntoView({ behavior: "smooth" });
}, []);

return (
<div className="landing-page">
{/* HERO */}
Expand Down Expand Up @@ -263,24 +278,12 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onTryIt }) => {
</p>

<ul className="landing-text landing-why-list">
<li>{"See how types actually evaluate, step by step"}</li>
<li>
<span aria-hidden="true">{"🔍"}</span>
<span>{"See how types actually evaluate, step by step"}</span>
</li>
<li>
<span aria-hidden="true">{"🧠"}</span>
<span>
{"Understand "}<code className="landing-code">{"extends"}</code>{", "}<code className="landing-code">{"infer"}</code>{", and mapped types visually"}
</span>
</li>
<li>
<span aria-hidden="true">{"🐞"}</span>
<span>{"Debug type errors without trial-and-error"}</span>
</li>
<li>
<span aria-hidden="true">{"📚"}</span>
<span>{"Learn advanced TypeScript faster"}</span>
{"Understand "}<code className="landing-code">{"extends"}</code>{", "}<code className="landing-code">{"infer"}</code>{", and mapped types visually"}
</li>
<li>{"Debug type errors without trial-and-error"}</li>
<li>{"Learn advanced TypeScript faster"}</li>
</ul>

<p className="landing-text-muted">
Expand All @@ -304,9 +307,6 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onTryIt }) => {
{"A quick walkthrough showing how a complex type turns into a clear, step-by-step explanation."}
</p>
</div>
<a href="#try" className="landing-link">
{"Back to Try It"}
</a>
</div>

{/* Demo Video */}
Expand Down Expand Up @@ -419,6 +419,28 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onTryIt }) => {
</a>
</div>
</footer>

{/* Scroll to Try It button */}
{showScrollTop && (
<button
type="button"
onClick={scrollToTry}
className="landing-scroll-top"
aria-label="Scroll to Try It section"
>
<svg
className="landing-icon-md"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<polyline points="18 15 12 9 6 15" />
</svg>
</button>
)}
</div>
);
};
Loading