UNPKG

chrome-devtools-frontend

Version:
138 lines (102 loc) 8.14 kB
--- name: ui-eng-vision-local-lit-renderer description: Migrates legacy imperative DOM construction to local declarative Lit-html templates rendered inside existing containers. allowed-tools: code_search open_urls --- # Subskill: Local Lit-HTML Renderer (Pass 2) This subskill converts consolidated imperative DOM construction helper methods into reactive, declarative Lit-html templates, rendering them locally inside the existing element containers. -------------------------------------------------------------------------------- ## 1. Declarative Technology Migration 1. **Conserve Abstraction Topology**: * Maintain the existing class hierarchy, helper class boundaries, and logical groups. * Do not aggressively "flatten" classes or collapse helper abstractions into the main view just to coerce a single master template. Pass 2 should only change the *implementation details* of rendering (imperative -> declarative) within existing compartments, not the public API or responsibilities of objects. 2. **Determine Render Lifecycle per Layer**: * **For UI.Widget classes**: Define or update `performUpdate()` to execute the main lit `render` call, and use `this.requestUpdate()` to queue updates. * **For Delegate/Helper classes**: Identify the custom update hook (e.g., `update()` or `scheduleUpdate()`) and invoke `render()` directly inside that method. **Do not** introduce Widget lifecycle methods (`performUpdate`) on classes that do not inherit them. 3. **Import Modern Templating**: * Import the `Lit` rendering system inside the view module: ```typescript import {html, render, nothing} from '../../ui/lit/lit.js'; ``` 4. **Modern Component Mapping**: * **MANDATORY**: You **MUST** read and load [ui_engineering.md](../../../docs/ui_engineering.md) first to understand specific component mappings (e.g., Toolbar vs `devtools-toolbar`). Do not assume standard Lit defaults. * If unsure, also consult the [automatic migration code](../../../scripts/eslint_rules/lib/no-imperative-dom-api.ts) * **Prefer Component Built-Ins Over Legacy Boilerplate**: Before porting legacy event handlers, comparators, or state variables, check if the modern component handles them natively. Drop host-level workarounds in favor of declarative component attributes. 5. **Local Modular Renders**: * If the class contains multiple separate legacy container fields (e.g., fields generated by `appendField` or `createChild` on a parent layout), prefer **local modular renders** (rendering templates individually into each container) to preserve the legacy layout framework. Do not force a monolithic template if doing so violates the existing topology. 6. **Resolve TypeScript Type Friction**: * Legacy DevTools elements may be typed as `Element`. Lit's `render()` function expects `HTMLElement | DocumentFragment`. * When rendering into legacy containers, cast the container using `as HTMLElement` or update its class property type definition from `Element` to `HTMLElement` to satisfy the TypeScript compiler. * Example: `render(this.template(), this.containerField as HTMLElement);` 7. **Delegate to Unmigrated Rendering Engines**: * Do not attempt to rewrite complex historical subsystems (like Linkifiers or specialized UI utilities) to be "pure Lit" during this pass. * Capitalize on Lit's ability to interpolate standard `HTMLElement` or `Element` instances directly. Treat unmigrated utilities as "black boxes" that generate DOM, and embed their output in standard template expressions: `html`<div>${this.legacyElement}</div>``. * **CRITICAL:** Before treating any component as "unmigrated," you MUST follow steps in Section 4. You are only allowed to use this escape hatch if no declarative migration instructions exist. 8. **Handle Asynchronous DOM Updates**: * For asynchronous callback-driven updates (e.g., elements updated in a `.then()` callback), render the parent container or a placeholder template first. Once the data is retrieved, execute a local `render()` inside the callback targeting the specific sub-container. 9. **Template Factorization Strategies**: * **Prefer `nothing`**: Use Lit's `nothing` sentinel instead of empty strings `''` or empty templates for conditional rendering. * **Parameterized Fragment Factories**: For repeated UI patterns or intermediate layout branches, extract them into parameterized helper functions inside the class scope returning `LitTemplate`. This avoids monoliths, preserves readability, and reuses template cache strategies. 10. **Visual Parity, CSS Adaptation, and Accessibility**: * **Zero-Tolerance Regression**: Screenshot tests are the ground truth for this phase. Any visual diff (above 0%) in the generated screenshots is unacceptable and must be resolved before proceeding. * **CSS Selector Migration**: When replacing legacy imperative components/widgets with modern web components (e.g., replacing legacy `DataGrid` with `<devtools-data-grid>`), inspect and update the associated `.css` file. Replace legacy class selectors (`.data-grid`) with tag selectors (`devtools-data-grid`). * **Strict Tag/Class Parity**: Do not change tag types (e.g., `span` to `div`) or drop class names during template translation, as CSS may depend on them. * **Explicit Component Variants**: Modern Custom Element (e.g. `<devtools-button>`) defaults may not match legacy appearance. Explicitly bind `.data=${{variant: Buttons.Button.Variant.OUTLINED}}` (or appropriate variant) rather than relying on defaults. * **Accessibility Preservation**: Convert custom accessibility instrumentation (like `ARIAUtils.markAsAlert()`) to native ARIA attributes in the template (e.g., `role="alert"`, `aria-live="polite"`). 11. **Render Templates Syntax & Code Movement**: * Surround the expressions containing lit template literals with `// clang-format off` and `// clang-format on` to prevent clang-format from corrupting template indentation. * **Minimize Code Movement**: Avoid moving existing code to a different location in the file. Put the function signature around the existing code to minimize the diff. * The Gerrit Code Review UI cannot identify moved blocks of unchanged code. * If blocks of code need to be reordered, create a "prefactoring" change that first extracts the code that needs to be reordered into a named helper functions and pause the migration, waiting user confirmation. 12. **Micro-Commit Strategy**: * Do not attempt to convert every helper method and UI component in a single monolithic commit. Break the template extraction into **small, self-contained micro-commits** (e.g., migrating one helper method, toolbar button, or list item render at a time). * Verify with build and run tests after each micro-commit to guarantee zero regressions and 100% visual parity before moving to the next compartment. * Provide the exact list of files and commit message when presenting progress so the change history remains atomic and easy to review. 13. **Wait for confirmation**: * Wait for an explicit confirmation from the user (or Parent Orchestrator Agent) before proceeding to the next step. -------------------------------------------------------------------------------- ## 🔍 Mental Audit (Internal Self-Correction) *Before reporting back or committing, re-read the instructions and verify:* 1.**Tag Parity**: Did I accidentally change any `span` to `div` (or vice versa)? 2.**Attribute Drop**: Did I drop any `aria-*`, `role`, or custom data attributes? 3.**Clang-Off Boundary**: Is the template wrapped in `// clang-format off`? 4.**Build**: Does the code compile and do visual tests pass with 0% diff?