Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

The @controller decorator derives element names from class names via kebab-case conversion, which breaks when class names are minified in production builds.

Changes

  • src/controller.ts: Add function overload accepting optional string parameter for explicit element name
  • src/core.ts: Thread optional elementName parameter through CatalystDelegate constructor
  • src/register.ts: Use provided name instead of deriving from class name when present
  • test/controller.ts: Add tests for decorator and function syntax with custom names
  • docs/_guide/your-first-component.md: Document custom name syntax and minification use case

Usage

// Existing behavior unchanged
@controller
class HelloWorldElement extends HTMLElement {}
// → registers as <hello-world>

// New: explicit name survives minification
@controller('happy-widget')
class SomeClass extends HTMLElement {}
// → registers as <happy-widget>

// Function syntax also supported
controller('my-element')(class Foo extends HTMLElement {})

Backward compatible—omitting the parameter preserves existing automatic naming behavior.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • accounts.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3528 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-Ygvhnb --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,12664389469337770198,2372341684580270968,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --disable-REDACTED-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=Translate,BackForwardCache --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-sync --force-color-profile=srgb --metrics-recording-only (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3848 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-ZW8rdt --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13741986308328416240,10430580951888999949,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • clients2.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3528 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-Ygvhnb --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,12664389469337770198,2372341684580270968,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --disable-REDACTED-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=Translate,BackForwardCache --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-sync --force-color-profile=srgb --metrics-recording-only (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3848 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-ZW8rdt --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13741986308328416240,10430580951888999949,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • safebrowsingohttpgateway.googleapis.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3528 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-Ygvhnb --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,12664389469337770198,2372341684580270968,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --disable-REDACTED-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=Translate,BackForwardCache --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-sync --force-color-profile=srgb --metrics-recording-only (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3848 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-ZW8rdt --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13741986308328416240,10430580951888999949,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • www.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3528 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-Ygvhnb --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,12664389469337770198,2372341684580270968,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --disable-REDACTED-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=Translate,BackForwardCache --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-sync --force-color-profile=srgb --metrics-recording-only (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=3848 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-ZW8rdt --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13741986308328416240,10430580951888999949,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=BackForwardCache,PaintHolding,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add optional syntax for custom element naming Add optional element name parameter to @controller decorator Jan 19, 2026
Copilot AI requested a review from dgreif January 19, 2026 12:11
@dgreif dgreif force-pushed the copilot/add-controller-name-override branch from c09e428 to fff47a5 Compare January 19, 2026 13:23
@dgreif dgreif changed the base branch from main to dg/fix-main January 19, 2026 13:24
Base automatically changed from dg/fix-main to main January 20, 2026 15:17
An error occurred while trying to automatically change base from dg/fix-main to main January 20, 2026 15:17
Copilot AI and others added 5 commits January 20, 2026 10:17
Co-authored-by: dgreif <3026298+dgreif@users.noreply.github.com>
Co-authored-by: dgreif <3026298+dgreif@users.noreply.github.com>
Co-authored-by: dgreif <3026298+dgreif@users.noreply.github.com>
@dgreif dgreif force-pushed the copilot/add-controller-name-override branch from 8d5ce1d to 811be96 Compare January 20, 2026 15:17
@dgreif
Copy link
Contributor

dgreif commented Jan 20, 2026

I noticed the tests flake quite a bit on the lazy-define suite (which I'm not touching here), so I updated the Node version and set a hard 30s limit on test runs in an attempt to fix it

@dgreif dgreif marked this pull request as ready for review January 20, 2026 15:35
@dgreif dgreif requested a review from a team as a code owner January 20, 2026 15:35
Copilot AI review requested due to automatic review settings January 20, 2026 15:35
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for specifying custom element names in the @controller decorator to handle production builds where class names are minified. The decorator now accepts an optional string parameter for explicit element naming while maintaining backward compatibility with automatic name derivation from class names.

Changes:

  • Enhanced @controller decorator with function overloads to accept optional custom element name parameter
  • Updated core implementation to thread custom name through registration process
  • Added comprehensive test coverage for decorator and function syntax with custom names
  • Documented the new feature with examples and use cases
  • Updated Node.js version from 16 to 24 across CI/CD workflows and development containers
  • Increased test timeout to 30 seconds

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/controller.ts Added function overloads to support optional custom element name parameter
src/core.ts Updated CatalystDelegate constructor to accept and pass through optional element name
src/register.ts Modified to use provided custom name instead of deriving from class name when available
test/controller.ts Added tests for custom name registration with both decorator and function syntax
docs/_guide/your-first-component.md Documented custom element name syntax and minification use case
web-test-runner.config.js Increased test finish timeout to 30 seconds
.github/workflows/publish.yml Updated Node.js version from 16.x to 24.x
.github/workflows/nodejs.yml Updated Node.js version from 16.x to 24.x
.github/workflows/lighthouse.yml Updated Node.js version from 16.x to 24.x
.devcontainer/devcontainer.json Updated Node.js variant from 16 to 24
.devcontainer/Dockerfile Updated Node.js variant from 16 to 24

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +17 to +38
it('registers element with custom name when provided', async () => {
@controller('happy-widget')
class SomeClass extends HTMLElement {}
instance = await fixture(html`<happy-widget />`)
expect(instance).to.be.instanceof(SomeClass)
})

it('registers element with custom name using function syntax', async () => {
controller('custom-element-name')(class AnotherClass extends HTMLElement {})
instance = await fixture(html`<custom-element-name />`)
expect(instance).to.exist
})

it('adds data-catalyst to elements with custom names', async () => {
@controller('custom-named-element')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class CustomNamedElement extends HTMLElement {}

instance = await fixture(html`<custom-named-element />`)
expect(instance.hasAttribute('data-catalyst')).to.equal(true)
expect(instance.getAttribute('data-catalyst')).to.equal('')
})
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage is missing for edge cases when using custom element names. Consider adding tests for invalid custom element names (e.g., names without hyphens, reserved names, uppercase characters) to verify that appropriate errors are thrown or handled correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +12
export function register(classObject: CustomElementClass, name?: string): CustomElementClass {
const tagName = name || dasherize(classObject.name).replace(/-element$/, '')
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom element name parameter is not validated. According to the HTML specification, custom element names must contain a hyphen to avoid conflicts with standard HTML elements. Consider adding validation to ensure the provided name contains a hyphen and follows custom element naming rules, or rely on the browser's customElements.define to throw appropriate errors for invalid names.

Copilot uses AI. Check for mistakes.
@dgreif dgreif merged commit 3f73d7a into main Jan 20, 2026
12 checks passed
@dgreif dgreif deleted the copilot/add-controller-name-override branch January 20, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants