Skip to content

Add ElementInternals support via options.internals #133

Description

@stefrado

Feature Request

Add support for the ElementInternals API by calling attachInternals() on construction and exposing it via an options.internals key or as static property.

Motivation

To build accessible web components, we need to be able to set the correct ARIA attributes on custom elements. The ElementInternals API provides aria properties (e.g. role, aria-label) that allow setting these semantics in a standards-compliant way - but this is currently not possible.

Proposed API

// Passed as option
register(MyForm, 'my-form', [], { internals: { role: "group" } });

// Or as static property
MyForm.internals = { role: "group" }

The internals value would be Partial<ElementInternals> whose entries are assigned to the ElementInternals instance at construction time.

Possible implementation

I tested this locally and this worked for me.

class PreactElement extends HTMLElement {
		constructor() {
			super();
			this._vdomComponent = Component;

			this._internals = this.attachInternals();

			if (options && options.internals) {
				Object.entries(options.internals).forEach(
					([k, v]) => (this._internals[k] = v)
				);
			}

			if (options && options.shadow) {
				this._root = this.attachShadow({
					mode: options.mode || 'open',
					serializable: options.serializable ?? false,
				});

				if (options.adoptedStyleSheets) {
					this._root.adoptedStyleSheets = options.adoptedStyleSheets;
				}
			} else {
				this._root = this;
			}
		}

		connectedCallback() {
			connectedCallback.call(this, options);
		}

		attributeChangedCallback(name, oldValue, newValue) {
			attributeChangedCallback.call(
				/** @type {PreactCustomElement} */ (/** @type {unknown} */ (this)),
				name,
				oldValue,
				newValue
			);
		}

		disconnectedCallback() {
			disconnectedCallback.call(this);
		}
	}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions