Repository navigation
Write the frontend as TypeScript LitElements - #468
Merged
Merged
Conversation
The frontend can hold TypeScript modules: cargo build strips their types with Node.js and the server serves the result at the source path, beside Lit embedded from frontend/node_modules. The pagination and its page buttons are the first LitElement components, and a reattached pagination no longer reports one click twice. CI checks types with tsc, formats and lints the .ts files with Biome, and runs on Node.js 24.
The app update, update result, Codex runtime restart and update, Codex reset credit, Claude runtime restart, and archived Task delete dialogs render through Lit. Opening and closing wait for the dialog's first render, so an owner can call them right after mounting it. Contracts that scanned only .js modules now scan the .ts ones too.
Every module in frontend/components/ renders through Lit, with file-status and chunked-fetch, which they use whole; other modules they call stay JavaScript behind a same-stem .d.ts. A component renders on the spot when it connects and when a public method changes it, since its JavaScript owners read its DOM right after.
Task Detail's Review, Git, and GitHub surfaces are TypeScript LitElements that hand files, diffs, and snapshots to their children as template properties. The shared viewers stop rendering in place on connect; only the three Detail layouts still flush for their JavaScript owner.
The Settings and Notes workspaces, their navigators and pages, and the shared workspace brand are TypeScript LitElements. The two workspaces still draw in place for the JavaScript Task Workspace that owns them.
The Task conversation, its entry model, and the components its entries mount are TypeScript LitElements. The list draws in place, entries included, for the JavaScript Task layout and the keyboard modes that read it right after a change.
The Composer with its attachments, context usage, voice input, and turn options, and New Task's Task Create and directory field, are TypeScript LitElements that draw in place for their JavaScript owners. Model menu options now survive a redraw, so an open Action Hint session keeps its keys.
The Task navigator, the Active list with its Sections and rows, the Archived list, and the Task switcher are TypeScript LitElements. The status chip is now one component every Task surface uses, and it registers its spinner once.
The Detail layout, the Task screen with its session and history, the Section screen with its shortcuts and fork dialog, the summary with Task Info, the Git and GitHub menus, and the terminal are TypeScript LitElements. The Task screen's conversation pane stays once drawn, and what stands in its place draws beside it.
The App Shell, the workspace with its tab buttons and update Task dialog, the Tasks layout, New Task, the recovery screens, the image preview, and the build mismatch alert are TypeScript LitElements. Workspace methods that nothing called, or that called a missing method, are gone.
Settings and appearance, the API, routes and navigation history, the Tasks model and stream, Codex and Task-store status, live updates and watch, foreground recovery, and the PWA update lifecycle are TypeScript. Their hand-written declarations are gone, and server response types live in the API module.
Each component declares its Action Hint targets, Scroll surfaces, and keyboard contexts on the elements its template draws, and reaches its own elements through drawn refs instead of selectors. The keyboard navigation controller and its badge, Scroll, and shortcut help parts are TypeScript.
Action Hint, Scroll, and keyboard-context declarations are read as the last draw left them instead of forcing each owner to draw first. Opening the Task switcher, continuing into a popover, and revalidating after a DOM change wait one frame, by which Lit has drawn the change.
The shell's entry module is TypeScript like the modules it loads. The string icon and HTML escaping helpers nothing used are gone, and the icon fixture contract now reads the inlineIcon calls production makes.
Components no longer draw when they connect, and those that only render their state keep it in reactive properties instead of drawing by hand. Immediate draws stay where the same call uses what it drew and in the routed layouts that hand their children a route right after drawing.
Node's type stripping limited the frontend to `.ts` import paths and erasable syntax, behind a separate script. tsc now compiles each module, the service worker included, to the `.js` path it is served at with a source map beside it, stops the server build on a type error, and writes the build unit tests run from. Keyboard navigation imports Action Hints through its public entry again, which the boundary contract checks now that imports end in `.js`.
A reactive field was spread over `static properties`, a `declare` line, and a constructor assignment. Components now declare it as a decorated `accessor` field and register with `@customElement`, lifecycle members carry `override`, and each tag has an `HTMLElementTagNameMap` entry. tsc imports the decorator helpers from `tslib`, which the server serves beside Lit's decorator modules.
Listeners restated each custom event's detail in a cast or parameter, so a sender could change it unseen. Each event that carries a detail now declares its type and DOM event map entry once, in the module a counted rule picks, with an -event module for the four that several modules both send and hear. A contract test checks the rule, and listeners no longer cast.
tsc now reports a function that returns a value on some paths and falls off the end on others. The App Shell's bootstrap was the only one, and both of its callers ignore the result, so it no longer returns it.
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://typescript-lit-element-caffold.taehoon-moon.workers.dev (commit 601cc17)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
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.
Every frontend module is now TypeScript and every component a LitElement. Nothing is meant to look or behave differently; what changes is how the frontend renders, builds, is served, and is tested.
cargo buildcompiles the frontend with tsc (strict,noImplicitOverride,noImplicitReturns), the app and the service worker separately, and stops on a type error. Building needs Node.js 24 or newer andnpm ciinfrontend/, which installslit,tslib, andtypescript; the Rust checks and the release workflow runnpm ci --omit=devbefore Cargo..jspath with a.js.mapsource map that carries the TypeScript source;.tsURLs are not served. The shell starts from/assets/app.js. The service worker is compiled fromservice-worker.tsand keeps its URL.tslib, and Lit's decorator modules are served through the import map and precached. Components declare reactive properties and registration with standard decorators, whose downleveled form adds about 0.4 MB to the uncompressed modules.npm run typecheckandnpm run lint(Biome) are new and run in Frontend Tests.npm run test:unitruns the unit tests from tsc's output.