From ea5831117e33c5d30eda421a6111b4a1df4a2314 Mon Sep 17 00:00:00 2001 From: nodeGarden Date: Wed, 24 Dec 2025 21:51:53 +0100 Subject: [PATCH 1/5] fix: Restore visual design from feature/layout-updates (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: restore visual design from feature/layout-updates - Hero gradient: diagonal slate-950β†’slate-900β†’indigo-950 - Card backgrounds: transparent glass effect (rgba) - Features section: indigo-950 tint overlay - Title: pure white (#fff) with indigo-200 accent - Buttons: rgba transparency with proper hover states - Inputs/textareas: slate-950/80 background - Theme dropdown: glass effect with shadows - Example buttons: transparent with indigo hover πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * style: remove default underline from landing links πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * style: remove underline from landing button links πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * style: replace emoji bullets with regular disc bullets in Why section πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * style: landing page UI improvements - Indent why-list bullets more (1.75rem) - Align examples row to right with margin-left: auto - Add xxl horizontal padding to btn-outline - Remove "Back to Try It" link from See It in Action - Add floating scroll-to-top button (lower-right, appears on scroll) πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --------- Co-authored-by: Claude Co-authored-by: Adrian Elton-Browning --- src/web/components/LandingPage.tsx | 62 +++++--- src/web/styles.css | 222 ++++++++++++++++------------- 2 files changed, 167 insertions(+), 117 deletions(-) diff --git a/src/web/components/LandingPage.tsx b/src/web/components/LandingPage.tsx index 695cda7..fde7968 100644 --- a/src/web/components/LandingPage.tsx +++ b/src/web/components/LandingPage.tsx @@ -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"; @@ -120,6 +120,21 @@ export const LandingPage: React.FC = ({ 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 (
{/* HERO */} @@ -263,24 +278,12 @@ export const LandingPage: React.FC = ({ onTryIt }) => {

    +
  • {"See how types actually evaluate, step by step"}
  • - - {"See how types actually evaluate, step by step"} -
  • -
  • - - - {"Understand "}{"extends"}{", "}{"infer"}{", and mapped types visually"} - -
  • -
  • - - {"Debug type errors without trial-and-error"} -
  • -
  • - - {"Learn advanced TypeScript faster"} + {"Understand "}{"extends"}{", "}{"infer"}{", and mapped types visually"}
  • +
  • {"Debug type errors without trial-and-error"}
  • +
  • {"Learn advanced TypeScript faster"}

@@ -304,9 +307,6 @@ export const LandingPage: React.FC = ({ onTryIt }) => { {"A quick walkthrough showing how a complex type turns into a clear, step-by-step explanation."}

- - {"Back to Try It"} - {/* Demo Video */} @@ -419,6 +419,28 @@ export const LandingPage: React.FC = ({ onTryIt }) => { + + {/* Scroll to Try It button */} + {showScrollTop && ( + + )} ); }; diff --git a/src/web/styles.css b/src/web/styles.css index c3f1fab..c9fd6ce 100644 --- a/src/web/styles.css +++ b/src/web/styles.css @@ -370,17 +370,17 @@ input[type='range']::-moz-range-progress { /* Base landing page */ .landing-page { - background: var(--bg); - color: var(--foreground); + background: #020617; /* slate-950 */ + color: #f1f5f9; /* slate-100 */ min-height: 100vh; font-family: var(--font-sans); } -/* Hero section */ +/* Hero section - diagonal gradient with indigo tint */ .landing-hero { position: relative; - background: var(--bg); - border-color: var(--border); + background: linear-gradient(to bottom right, #020617, #0f172a, #1e1b4b); /* slate-950 via slate-900 to indigo-950 */ + border-color: rgba(255, 255, 255, 0.1); } /* Layout components */ @@ -446,6 +446,7 @@ input[type='range']::-moz-range-progress { display: flex; flex-wrap: wrap; gap: var(--spacing-sm); + margin-left: auto; } .landing-input-row { @@ -532,14 +533,14 @@ input[type='range']::-moz-range-progress { border-radius: var(--radius-full); font-size: var(--font-size-xs); line-height: 1rem; - background: var(--bg-highlight); - color: var(--text-secondary); - border: 1px solid var(--border); + background: rgba(255, 255, 255, 0.05); + color: #e2e8f0; /* slate-200 */ + border: 1px solid rgba(255, 255, 255, 0.1); } /* Title styling */ .landing-title { - color: var(--foreground); + color: #ffffff; font-size: 2.25rem; line-height: 2.5rem; font-weight: 800; @@ -548,12 +549,12 @@ input[type='range']::-moz-range-progress { } .landing-title-accent { - color: var(--accent-highlight); + color: #c7d2fe; /* indigo-200 */ } /* Subtitle */ .landing-subtitle { - color: var(--text-secondary); + color: #e2e8f0; /* slate-200 */ font-size: 1.125rem; line-height: 1.75rem; margin-top: var(--spacing-md); @@ -561,7 +562,7 @@ input[type='range']::-moz-range-progress { /* Headings */ .landing-heading { - color: var(--foreground); + color: #ffffff; } .landing-heading-lg { @@ -578,28 +579,27 @@ input[type='range']::-moz-range-progress { /* Text */ .landing-text { - color: var(--text-secondary); + color: #e2e8f0; /* slate-200 */ } .landing-text-muted { - color: var(--text-tertiary); + color: #cbd5e1; /* slate-300 */ } /* Labels */ .landing-label { - color: var(--text-secondary); + color: #e2e8f0; /* slate-200 */ font-size: var(--font-size-sm); } /* Links */ .landing-link { - color: var(--accent-highlight); - text-decoration: underline; - text-underline-offset: 4px; + color: #c7d2fe; /* indigo-200 */ + text-decoration: none; } .landing-link:hover { - color: var(--accent-primary-alt); + color: #e0e7ff; /* indigo-100 */ } /* Buttons */ @@ -607,19 +607,20 @@ input[type='range']::-moz-range-progress { display: inline-flex; align-items: center; justify-content: center; - padding: var(--spacing-md) var(--spacing-lg); - background: var(--accent-primary); - color: var(--btn-accent-text); + padding: var(--spacing-md) var(--spacing-xxl); + background: #6366f1; /* indigo-500 */ + color: #ffffff; border: none; border-radius: var(--radius-lg); font-weight: 600; font-size: var(--font-size-md); cursor: pointer; transition: var(--transition-fast); + text-decoration: none; } .landing-btn-primary:hover { - background: var(--accent-primary-alt); + background: #818cf8; /* indigo-400 */ } .landing-btn-secondary { @@ -627,78 +628,81 @@ input[type='range']::-moz-range-progress { align-items: center; justify-content: center; padding: var(--spacing-md) var(--spacing-lg); - background: var(--bg-highlight); - color: var(--foreground); - border: 1px solid var(--border-medium); + background: rgba(255, 255, 255, 0.05); + color: #f1f5f9; /* slate-100 */ + border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-lg); font-size: var(--font-size-md); cursor: pointer; transition: var(--transition-fast); + text-decoration: none; } .landing-btn-secondary:hover { - background: var(--bg-active); + background: rgba(255, 255, 255, 0.1); } .landing-btn-outline { display: inline-flex; align-items: center; justify-content: center; - padding: var(--spacing-md) var(--spacing-lg); + padding: var(--spacing-md) var(--spacing-xxl); background: transparent; - color: var(--foreground); - border: 1px solid var(--border-medium); + color: #f1f5f9; /* slate-100 */ + border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-lg); font-size: var(--font-size-md); cursor: pointer; transition: var(--transition-fast); + text-decoration: none; } .landing-btn-outline:hover { - background: var(--bg-highlight); + background: rgba(255, 255, 255, 0.05); } /* Cards */ .landing-card { - background: var(--bg-secondary); - border: 1px solid var(--border); + background: rgba(15, 23, 42, 0.6); /* slate-900/60 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 1rem; padding: var(--spacing-xxl); + box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04); } .landing-card-alt { - background: var(--bg-secondary); - border: 1px solid var(--border); + background: rgba(15, 23, 42, 0.4); /* slate-900/40 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 1rem; padding: var(--spacing-xxl); } .landing-card-inner { - background: var(--bg-highlight); - border: 1px solid var(--border); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.75rem; padding: var(--spacing-xxl); } -/* Features section */ +/* Features section - with indigo tint */ .landing-features-card { - background: var(--bg-secondary); - border: 1px solid var(--border); + background: rgba(30, 27, 75, 0.35); /* indigo-950/35 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 1rem; padding: var(--spacing-xxl); } .landing-feature-card { - background: var(--bg-highlight); - border: 1px solid var(--border); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.75rem; padding: var(--spacing-lg); } /* Code styling */ .landing-code { - background: var(--bg-highlight); - color: var(--text-secondary); + background: rgba(255, 255, 255, 0.1); + color: #e2e8f0; /* slate-200 */ font-family: var(--font-mono); padding: 0.125rem 0.375rem; border-radius: var(--radius-sm); @@ -707,9 +711,9 @@ input[type='range']::-moz-range-progress { /* Input fields */ .landing-input { - background: var(--bg); - color: var(--foreground); - border: 1px solid var(--border); + background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + color: #f1f5f9; /* slate-100 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: var(--radius-lg); padding: var(--spacing-xs) var(--spacing-sm); font-family: var(--font-mono); @@ -717,37 +721,37 @@ input[type='range']::-moz-range-progress { } .landing-input:focus { - border-color: var(--accent-primary); + border-color: #6366f1; /* indigo-500 */ outline: none; box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); } .landing-input::placeholder { - color: var(--text-tertiary); + color: #64748b; /* slate-500 */ } /* Textarea */ .landing-textarea { - background: var(--bg); - color: var(--foreground); - border: 1px solid var(--border); + background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + color: #f1f5f9; /* slate-100 */ + border: 1px solid rgba(255, 255, 255, 0.1); } .landing-textarea:focus { - border-color: var(--accent-primary); + border-color: #6366f1; /* indigo-500 */ outline: none; box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); } .landing-textarea::placeholder { - color: var(--text-tertiary); + color: #64748b; /* slate-500 */ } /* Output area */ .landing-output { - background: var(--bg); - color: var(--foreground); - border: 1px solid var(--border); + background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + color: #f1f5f9; /* slate-100 */ + border: 1px solid rgba(255, 255, 255, 0.1); font-family: var(--font-mono); border-radius: var(--radius-lg); padding: var(--spacing-md); @@ -759,8 +763,8 @@ input[type='range']::-moz-range-progress { /* Video container */ .landing-video-container { position: relative; - background: var(--bg); - border: 1px solid var(--border); + background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.75rem; overflow: hidden; margin-top: var(--spacing-md); @@ -773,7 +777,7 @@ input[type='range']::-moz-range-progress { display: flex; align-items: center; justify-content: center; - background: var(--bg-highlight) url('/ts-debugger-poster.jpg') center/contain no-repeat; + background: rgba(30, 41, 59, 0.8) url('/ts-debugger-poster.jpg') center/contain no-repeat; /* slate-800/80 */ cursor: pointer; border: none; z-index: 1; @@ -789,8 +793,8 @@ input[type='range']::-moz-range-progress { /* Video placeholder (legacy) */ .landing-video-placeholder { - background: var(--bg); - border: 1px solid var(--border); + background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.75rem; overflow: hidden; margin-top: var(--spacing-md); @@ -807,7 +811,7 @@ input[type='range']::-moz-range-progress { .landing-video-gradient { position: absolute; inset: 0; - background: linear-gradient(to bottom right, var(--bg-highlight), transparent, var(--accent-primary)); + background: linear-gradient(to bottom right, #1e293b, transparent, #6366f1); /* slate-800 to indigo-500 */ opacity: 0.1; } @@ -819,24 +823,24 @@ input[type='range']::-moz-range-progress { height: 3.5rem; border-radius: 9999px; margin: 0 auto; - background: var(--bg-highlight); - border: 1px solid var(--border); - color: var(--foreground); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + color: #f1f5f9; /* slate-100 */ font-size: 1.5rem; } /* Footer */ .landing-footer { background: transparent; - border-color: var(--border); - color: var(--text-tertiary); + border-color: rgba(255, 255, 255, 0.1); + color: #64748b; /* slate-500 */ padding: 2rem 0; } .landing-footer-divider { width: 1px; height: 1.25rem; - background: var(--border-medium); + background: rgba(255, 255, 255, 0.2); } /* Light theme overrides - only for shadow enhancements */ @@ -852,16 +856,16 @@ body.theme-light .landing-card { width: 2.25rem; height: 2.25rem; border-radius: var(--radius-lg); - background: var(--bg-highlight); - border: 1px solid var(--border); - color: var(--foreground); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + color: #f1f5f9; /* slate-100 */ font-size: 1.125rem; cursor: pointer; transition: var(--transition-fast); } .landing-theme-btn:hover { - background: var(--bg-active); + background: rgba(255, 255, 255, 0.1); } .landing-theme-menu { @@ -873,9 +877,9 @@ body.theme-light .landing-card { border-radius: var(--radius-lg); overflow: hidden; z-index: var(--z-dropdown); - background: var(--bg-secondary); - border: 1px solid var(--border); - box-shadow: var(--shadow-md); + background: rgba(15, 23, 42, 0.95); /* slate-900/95 */ + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); } .landing-theme-option { @@ -887,58 +891,82 @@ body.theme-light .landing-card { font-size: var(--font-size-sm); text-align: left; background: transparent; - color: var(--text-secondary); + color: #94a3b8; /* slate-400 */ border: none; cursor: pointer; transition: var(--transition-fast); } .landing-theme-option:hover { - background: var(--bg-highlight); + background: rgba(255, 255, 255, 0.05); } .landing-theme-option.selected { - background: var(--bg-active); - color: var(--accent-highlight); + background: rgba(255, 255, 255, 0.1); + color: #a5b4fc; /* indigo-300 */ } .landing-theme-check { - color: var(--accent-primary); + color: #6366f1; /* indigo-500 */ } /* Example buttons */ .landing-example-btn { padding: var(--spacing-sm) var(--spacing-md); font-size: var(--font-size-sm); - border: 1px solid var(--border-medium); + border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-sm); background: transparent; - color: var(--foreground); + color: #f1f5f9; /* slate-100 */ cursor: pointer; transition: var(--transition-fast); } .landing-example-btn:hover { - background: var(--bg-highlight); - border-color: var(--accent-primary); + background: rgba(255, 255, 255, 0.05); + border-color: #6366f1; /* indigo-500 */ } .landing-example-btn.selected { - background: var(--bg-active); - border-color: var(--accent-primary); - color: var(--accent-highlight); + background: rgba(255, 255, 255, 0.1); + border-color: #6366f1; /* indigo-500 */ + color: #a5b4fc; /* indigo-300 */ } /* Why list */ .landing-why-list { - list-style: none; - padding-left: 0; + list-style: disc; + padding-left: 1.75rem; + margin-top: var(--spacing-md); } .landing-why-list li { + margin-top: var(--spacing-sm); +} + +/* Scroll to top button */ +.landing-scroll-top { + position: fixed; + bottom: 2rem; + right: 2rem; display: flex; - gap: var(--spacing-sm); - margin-top: var(--spacing-md); + align-items: center; + justify-content: center; + width: 3rem; + height: 3rem; + border-radius: 9999px; + background: rgba(99, 102, 241, 0.9); /* indigo-500/90 */ + border: 1px solid rgba(255, 255, 255, 0.2); + color: #ffffff; + cursor: pointer; + transition: var(--transition-fast); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: var(--z-fixed); +} + +.landing-scroll-top:hover { + background: #818cf8; /* indigo-400 */ + transform: translateY(-2px); } /* GitHub link for landing page */ @@ -949,15 +977,15 @@ body.theme-light .landing-card { width: 2.25rem; height: 2.25rem; border-radius: var(--radius-lg); - background: var(--bg-highlight); - border: 1px solid var(--border); - color: var(--text-secondary); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + color: #94a3b8; /* slate-400 */ transition: var(--transition-fast); } .landing-github-link:hover { - background: var(--bg-active); - color: var(--foreground); + background: rgba(255, 255, 255, 0.1); + color: #f1f5f9; /* slate-100 */ } /* Icon sizing */ From 263a998cd3ffddb4237b158733de3f07a90d57ba Mon Sep 17 00:00:00 2001 From: Adrian Elton-Browning Date: Tue, 30 Dec 2025 18:17:19 +0000 Subject: [PATCH 2/5] refactor: Consolidate hardcoded CSS values into CSS variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add glass effect variables (--glass-5, --glass-10, --glass-card, etc.) - Add extended text colors (--text-white, --text-light, --text-muted) - Add indigo shades (--indigo-lighter, --indigo-dark) - Add focus ring and hero gradient variables - Replace all hardcoded rgba/hex values in landing page styles - Add light theme overrides for all new variables πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/web/styles.css | 230 +++++++++++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 93 deletions(-) diff --git a/src/web/styles.css b/src/web/styles.css index c9fd6ce..14a0598 100644 --- a/src/web/styles.css +++ b/src/web/styles.css @@ -23,6 +23,15 @@ --border-subtle: rgba(255, 255, 255, 0.1); --border-medium: rgba(255, 255, 255, 0.2); + /* Glass effects */ + --glass-5: rgba(255, 255, 255, 0.05); + --glass-10: rgba(255, 255, 255, 0.1); + --glass-card: rgba(15, 23, 42, 0.6); /* slate-900/60 */ + --glass-card-alt: rgba(15, 23, 42, 0.4); /* slate-900/40 */ + --glass-input: rgba(2, 6, 23, 0.8); /* slate-950/80 */ + --glass-menu: rgba(15, 23, 42, 0.95); /* slate-900/95 */ + --glass-features: rgba(30, 27, 75, 0.35); /* indigo-950/35 */ + /* Accent colors - Indigo palette */ --accent-primary: #6366f1; /* indigo-500 */ --accent-primary-alt: #818cf8; /* indigo-400 */ @@ -41,7 +50,20 @@ --red: #ef4444; /* red-500 */ --yellow: #fde047; /* yellow-300 */ --indigo: #818cf8; /* indigo-400 */ - --indigo-light: #c7d2fe; /* indigo-200 */ + --indigo-light: #c7d2fe; /* indigo-200 */ + --indigo-lighter: #e0e7ff; /* indigo-100 */ + --indigo-dark: #1e1b4b; /* indigo-950 */ + + /* Extended text colors */ + --text-white: #ffffff; + --text-light: #e2e8f0; /* slate-200 */ + --text-muted: #cbd5e1; /* slate-300 */ + + /* Focus ring */ + --focus-ring: rgba(99, 102, 241, 0.3); + + /* Hero gradient */ + --landing-hero-gradient: linear-gradient(to bottom right, var(--bg), var(--bg-secondary), var(--indigo-dark)); /* Syntax highlighting */ --syntax-keyword: #f472b6; /* pink-400 */ @@ -220,6 +242,28 @@ body.theme-light { --step-indexed-access-result: #16a34a; --step-type-alias-start: #64748b; + /* Glass effects - light theme uses semi-transparent with actual color values */ + --glass-5: rgba(0, 0, 0, 0.03); + --glass-10: rgba(0, 0, 0, 0.06); + --glass-card: rgba(255, 255, 255, 0.8); + --glass-card-alt: rgba(255, 255, 255, 0.6); + --glass-input: rgba(255, 255, 255, 0.9); + --glass-menu: rgba(255, 255, 255, 0.98); + --glass-features: rgba(224, 231, 255, 0.4); /* indigo-100/40 */ + + /* Extended text colors - light theme */ + --text-white: #0f172a; /* inverted for light theme - slate-900 */ + --text-light: #334155; /* slate-700 */ + --text-muted: #475569; /* slate-600 */ + --indigo-lighter: #c7d2fe; /* indigo-200 */ + --indigo-dark: #312e81; /* indigo-900 for light gradient */ + + /* Focus ring - light theme */ + --focus-ring: rgba(79, 70, 229, 0.25); + + /* Hero gradient - light theme */ + --landing-hero-gradient: linear-gradient(to bottom right, var(--bg), var(--bg-secondary), rgba(199, 210, 254, 0.5)); + /* Shadows - light theme uses subtle shadows */ --shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.08); --shadow-md: 0 2px 6px rgba(15, 23, 42, 0.1); @@ -370,8 +414,8 @@ input[type='range']::-moz-range-progress { /* Base landing page */ .landing-page { - background: #020617; /* slate-950 */ - color: #f1f5f9; /* slate-100 */ + background: var(--bg); + color: var(--foreground); min-height: 100vh; font-family: var(--font-sans); } @@ -379,8 +423,8 @@ input[type='range']::-moz-range-progress { /* Hero section - diagonal gradient with indigo tint */ .landing-hero { position: relative; - background: linear-gradient(to bottom right, #020617, #0f172a, #1e1b4b); /* slate-950 via slate-900 to indigo-950 */ - border-color: rgba(255, 255, 255, 0.1); + background: var(--landing-hero-gradient); + border-color: var(--border); } /* Layout components */ @@ -533,14 +577,14 @@ input[type='range']::-moz-range-progress { border-radius: var(--radius-full); font-size: var(--font-size-xs); line-height: 1rem; - background: rgba(255, 255, 255, 0.05); - color: #e2e8f0; /* slate-200 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-5); + color: var(--text-light); + border: 1px solid var(--border); } /* Title styling */ .landing-title { - color: #ffffff; + color: var(--text-white); font-size: 2.25rem; line-height: 2.5rem; font-weight: 800; @@ -549,12 +593,12 @@ input[type='range']::-moz-range-progress { } .landing-title-accent { - color: #c7d2fe; /* indigo-200 */ + color: var(--indigo-light); } /* Subtitle */ .landing-subtitle { - color: #e2e8f0; /* slate-200 */ + color: var(--text-light); font-size: 1.125rem; line-height: 1.75rem; margin-top: var(--spacing-md); @@ -562,7 +606,7 @@ input[type='range']::-moz-range-progress { /* Headings */ .landing-heading { - color: #ffffff; + color: var(--text-white); } .landing-heading-lg { @@ -579,27 +623,27 @@ input[type='range']::-moz-range-progress { /* Text */ .landing-text { - color: #e2e8f0; /* slate-200 */ + color: var(--text-light); } .landing-text-muted { - color: #cbd5e1; /* slate-300 */ + color: var(--text-muted); } /* Labels */ .landing-label { - color: #e2e8f0; /* slate-200 */ + color: var(--text-light); font-size: var(--font-size-sm); } /* Links */ .landing-link { - color: #c7d2fe; /* indigo-200 */ + color: var(--indigo-light); text-decoration: none; } .landing-link:hover { - color: #e0e7ff; /* indigo-100 */ + color: var(--indigo-lighter); } /* Buttons */ @@ -608,8 +652,8 @@ input[type='range']::-moz-range-progress { align-items: center; justify-content: center; padding: var(--spacing-md) var(--spacing-xxl); - background: #6366f1; /* indigo-500 */ - color: #ffffff; + background: var(--accent-primary); + color: var(--text-white); border: none; border-radius: var(--radius-lg); font-weight: 600; @@ -620,7 +664,7 @@ input[type='range']::-moz-range-progress { } .landing-btn-primary:hover { - background: #818cf8; /* indigo-400 */ + background: var(--accent-primary-alt); } .landing-btn-secondary { @@ -628,9 +672,9 @@ input[type='range']::-moz-range-progress { align-items: center; justify-content: center; padding: var(--spacing-md) var(--spacing-lg); - background: rgba(255, 255, 255, 0.05); - color: #f1f5f9; /* slate-100 */ - border: 1px solid rgba(255, 255, 255, 0.2); + background: var(--glass-5); + color: var(--foreground); + border: 1px solid var(--border-medium); border-radius: var(--radius-lg); font-size: var(--font-size-md); cursor: pointer; @@ -639,7 +683,7 @@ input[type='range']::-moz-range-progress { } .landing-btn-secondary:hover { - background: rgba(255, 255, 255, 0.1); + background: var(--glass-10); } .landing-btn-outline { @@ -648,8 +692,8 @@ input[type='range']::-moz-range-progress { justify-content: center; padding: var(--spacing-md) var(--spacing-xxl); background: transparent; - color: #f1f5f9; /* slate-100 */ - border: 1px solid rgba(255, 255, 255, 0.2); + color: var(--foreground); + border: 1px solid var(--border-medium); border-radius: var(--radius-lg); font-size: var(--font-size-md); cursor: pointer; @@ -658,51 +702,51 @@ input[type='range']::-moz-range-progress { } .landing-btn-outline:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--glass-5); } /* Cards */ .landing-card { - background: rgba(15, 23, 42, 0.6); /* slate-900/60 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-card); + border: 1px solid var(--border); border-radius: 1rem; padding: var(--spacing-xxl); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04); } .landing-card-alt { - background: rgba(15, 23, 42, 0.4); /* slate-900/40 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-card-alt); + border: 1px solid var(--border); border-radius: 1rem; padding: var(--spacing-xxl); } .landing-card-inner { - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-5); + border: 1px solid var(--border); border-radius: 0.75rem; padding: var(--spacing-xxl); } /* Features section - with indigo tint */ .landing-features-card { - background: rgba(30, 27, 75, 0.35); /* indigo-950/35 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-features); + border: 1px solid var(--border); border-radius: 1rem; padding: var(--spacing-xxl); } .landing-feature-card { - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-5); + border: 1px solid var(--border); border-radius: 0.75rem; padding: var(--spacing-lg); } /* Code styling */ .landing-code { - background: rgba(255, 255, 255, 0.1); - color: #e2e8f0; /* slate-200 */ + background: var(--glass-10); + color: var(--text-light); font-family: var(--font-mono); padding: 0.125rem 0.375rem; border-radius: var(--radius-sm); @@ -711,9 +755,9 @@ input[type='range']::-moz-range-progress { /* Input fields */ .landing-input { - background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ - color: #f1f5f9; /* slate-100 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-input); + color: var(--foreground); + border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--spacing-xs) var(--spacing-sm); font-family: var(--font-mono); @@ -721,37 +765,37 @@ input[type='range']::-moz-range-progress { } .landing-input:focus { - border-color: #6366f1; /* indigo-500 */ + border-color: var(--accent-primary); outline: none; - box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); + box-shadow: 0 0 0 2px var(--focus-ring); } .landing-input::placeholder { - color: #64748b; /* slate-500 */ + color: var(--text-tertiary); } /* Textarea */ .landing-textarea { - background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ - color: #f1f5f9; /* slate-100 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-input); + color: var(--foreground); + border: 1px solid var(--border); } .landing-textarea:focus { - border-color: #6366f1; /* indigo-500 */ + border-color: var(--accent-primary); outline: none; - box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); + box-shadow: 0 0 0 2px var(--focus-ring); } .landing-textarea::placeholder { - color: #64748b; /* slate-500 */ + color: var(--text-tertiary); } /* Output area */ .landing-output { - background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ - color: #f1f5f9; /* slate-100 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-input); + color: var(--foreground); + border: 1px solid var(--border); font-family: var(--font-mono); border-radius: var(--radius-lg); padding: var(--spacing-md); @@ -763,8 +807,8 @@ input[type='range']::-moz-range-progress { /* Video container */ .landing-video-container { position: relative; - background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-input); + border: 1px solid var(--border); border-radius: 0.75rem; overflow: hidden; margin-top: var(--spacing-md); @@ -777,7 +821,7 @@ input[type='range']::-moz-range-progress { display: flex; align-items: center; justify-content: center; - background: rgba(30, 41, 59, 0.8) url('/ts-debugger-poster.jpg') center/contain no-repeat; /* slate-800/80 */ + background: rgba(30, 41, 59, 0.8) url('/ts-debugger-poster.jpg') center/contain no-repeat; cursor: pointer; border: none; z-index: 1; @@ -793,8 +837,8 @@ input[type='range']::-moz-range-progress { /* Video placeholder (legacy) */ .landing-video-placeholder { - background: rgba(2, 6, 23, 0.8); /* slate-950/80 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-input); + border: 1px solid var(--border); border-radius: 0.75rem; overflow: hidden; margin-top: var(--spacing-md); @@ -811,7 +855,7 @@ input[type='range']::-moz-range-progress { .landing-video-gradient { position: absolute; inset: 0; - background: linear-gradient(to bottom right, #1e293b, transparent, #6366f1); /* slate-800 to indigo-500 */ + background: linear-gradient(to bottom right, var(--bg-highlight), transparent, var(--accent-primary)); opacity: 0.1; } @@ -823,24 +867,24 @@ input[type='range']::-moz-range-progress { height: 3.5rem; border-radius: 9999px; margin: 0 auto; - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - color: #f1f5f9; /* slate-100 */ + background: var(--glass-5); + border: 1px solid var(--border); + color: var(--foreground); font-size: 1.5rem; } /* Footer */ .landing-footer { background: transparent; - border-color: rgba(255, 255, 255, 0.1); - color: #64748b; /* slate-500 */ + border-color: var(--border); + color: var(--text-tertiary); padding: 2rem 0; } .landing-footer-divider { width: 1px; height: 1.25rem; - background: rgba(255, 255, 255, 0.2); + background: var(--border-medium); } /* Light theme overrides - only for shadow enhancements */ @@ -856,16 +900,16 @@ body.theme-light .landing-card { width: 2.25rem; height: 2.25rem; border-radius: var(--radius-lg); - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - color: #f1f5f9; /* slate-100 */ + background: var(--glass-5); + border: 1px solid var(--border); + color: var(--foreground); font-size: 1.125rem; cursor: pointer; transition: var(--transition-fast); } .landing-theme-btn:hover { - background: rgba(255, 255, 255, 0.1); + background: var(--glass-10); } .landing-theme-menu { @@ -877,8 +921,8 @@ body.theme-light .landing-card { border-radius: var(--radius-lg); overflow: hidden; z-index: var(--z-dropdown); - background: rgba(15, 23, 42, 0.95); /* slate-900/95 */ - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--glass-menu); + border: 1px solid var(--border); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); } @@ -891,46 +935,46 @@ body.theme-light .landing-card { font-size: var(--font-size-sm); text-align: left; background: transparent; - color: #94a3b8; /* slate-400 */ + color: var(--text-secondary); border: none; cursor: pointer; transition: var(--transition-fast); } .landing-theme-option:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--glass-5); } .landing-theme-option.selected { - background: rgba(255, 255, 255, 0.1); - color: #a5b4fc; /* indigo-300 */ + background: var(--glass-10); + color: var(--accent-highlight); } .landing-theme-check { - color: #6366f1; /* indigo-500 */ + color: var(--accent-primary); } /* Example buttons */ .landing-example-btn { padding: var(--spacing-sm) var(--spacing-md); font-size: var(--font-size-sm); - border: 1px solid rgba(255, 255, 255, 0.2); + border: 1px solid var(--border-medium); border-radius: var(--radius-sm); background: transparent; - color: #f1f5f9; /* slate-100 */ + color: var(--foreground); cursor: pointer; transition: var(--transition-fast); } .landing-example-btn:hover { - background: rgba(255, 255, 255, 0.05); - border-color: #6366f1; /* indigo-500 */ + background: var(--glass-5); + border-color: var(--accent-primary); } .landing-example-btn.selected { - background: rgba(255, 255, 255, 0.1); - border-color: #6366f1; /* indigo-500 */ - color: #a5b4fc; /* indigo-300 */ + background: var(--glass-10); + border-color: var(--accent-primary); + color: var(--accent-highlight); } /* Why list */ @@ -955,9 +999,9 @@ body.theme-light .landing-card { width: 3rem; height: 3rem; border-radius: 9999px; - background: rgba(99, 102, 241, 0.9); /* indigo-500/90 */ - border: 1px solid rgba(255, 255, 255, 0.2); - color: #ffffff; + background: rgba(99, 102, 241, 0.9); + border: 1px solid var(--border-medium); + color: var(--text-white); cursor: pointer; transition: var(--transition-fast); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); @@ -965,7 +1009,7 @@ body.theme-light .landing-card { } .landing-scroll-top:hover { - background: #818cf8; /* indigo-400 */ + background: var(--accent-primary-alt); transform: translateY(-2px); } @@ -977,15 +1021,15 @@ body.theme-light .landing-card { width: 2.25rem; height: 2.25rem; border-radius: var(--radius-lg); - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - color: #94a3b8; /* slate-400 */ + background: var(--glass-5); + border: 1px solid var(--border); + color: var(--text-secondary); transition: var(--transition-fast); } .landing-github-link:hover { - background: rgba(255, 255, 255, 0.1); - color: #f1f5f9; /* slate-100 */ + background: var(--glass-10); + color: var(--foreground); } /* Icon sizing */ From eacc5fbe95909236fd45e1a8e117886e8484ea07 Mon Sep 17 00:00:00 2001 From: Adrian Elton-Browning Date: Tue, 30 Dec 2025 18:24:18 +0000 Subject: [PATCH 3/5] refactor: Consolidate duplicate CSS color declarations to variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add shadow color variables (--shadow-color-light, --shadow-color-medium) - Add glass overlay variables (--glass-overlay-dark, --glass-accent-90) - Add composite shadow variables (--shadow-dropdown, --shadow-thumb) - Replace all hardcoded rgba values outside :root with CSS variables - Improves maintainability and theme consistency πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/web/styles.css | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/web/styles.css b/src/web/styles.css index 14a0598..1184b84 100644 --- a/src/web/styles.css +++ b/src/web/styles.css @@ -139,9 +139,20 @@ --transition-fast: all 0.15s ease; --transition-normal: all 0.3s ease; + /* Shadow colors */ + --shadow-color-light: rgba(0, 0, 0, 0.2); + --shadow-color-medium: rgba(0, 0, 0, 0.3); + --shadow-subtle-light: rgba(255, 255, 255, 0.04); + + /* Glass overlays */ + --glass-overlay-dark: rgba(30, 41, 59, 0.8); /* slate-800/80 */ + --glass-accent-90: rgba(99, 102, 241, 0.9); /* indigo-500/90 */ + /* Shadows - dark theme uses minimal shadows */ --shadow-sm: none; --shadow-md: none; + --shadow-dropdown: 0 4px 12px var(--shadow-color-medium); + --shadow-thumb: 0 2px 4px var(--shadow-color-light); --shadow-glow-green: 0 0 8px var(--green); --shadow-glow-purple: 0 0 8px var(--purple); @@ -314,7 +325,7 @@ input[type='range']::-webkit-slider-thumb { border-radius: 50%; background: var(--accent-highlight); cursor: pointer; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: var(--shadow-thumb); margin-top: -5px; } @@ -325,7 +336,7 @@ input[type='range']::-moz-range-thumb { background: var(--accent-highlight); cursor: pointer; border: none; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: var(--shadow-thumb); margin-top: -5px; } @@ -711,7 +722,7 @@ input[type='range']::-moz-range-progress { border: 1px solid var(--border); border-radius: 1rem; padding: var(--spacing-xxl); - box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04); + box-shadow: 0 0 0 1px var(--shadow-subtle-light); } .landing-card-alt { @@ -821,7 +832,7 @@ input[type='range']::-moz-range-progress { display: flex; align-items: center; justify-content: center; - background: rgba(30, 41, 59, 0.8) url('/ts-debugger-poster.jpg') center/contain no-repeat; + background: var(--glass-overlay-dark) url('/ts-debugger-poster.jpg') center/contain no-repeat; cursor: pointer; border: none; z-index: 1; @@ -923,7 +934,7 @@ body.theme-light .landing-card { z-index: var(--z-dropdown); background: var(--glass-menu); border: 1px solid var(--border); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + box-shadow: var(--shadow-dropdown); } .landing-theme-option { @@ -999,12 +1010,12 @@ body.theme-light .landing-card { width: 3rem; height: 3rem; border-radius: 9999px; - background: rgba(99, 102, 241, 0.9); + background: var(--glass-accent-90); border: 1px solid var(--border-medium); color: var(--text-white); cursor: pointer; transition: var(--transition-fast); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + box-shadow: var(--shadow-dropdown); z-index: var(--z-fixed); } From cd6c509604c940cb356032b1ea38336b0a477b95 Mon Sep 17 00:00:00 2001 From: Adrian Elton-Browning Date: Tue, 30 Dec 2025 18:24:41 +0000 Subject: [PATCH 4/5] chore(beads): Close task ts-ast-parser-eval-66k --- .beads/issues.jsonl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 6d147b1..d8ea0fd 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -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"}]} @@ -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"}]} From f06c5a025bb98930be02a4941439b5fc43cade1e Mon Sep 17 00:00:00 2001 From: Adrian Elton-Browning Date: Wed, 31 Dec 2025 11:57:55 +0000 Subject: [PATCH 5/5] chore: Claude Settings --- .claude/settings.local.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 3ef25b4..568cfad 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -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": []