From 8cdf6a35cc54566043b142235640e5641f88d328 Mon Sep 17 00:00:00 2001 From: Jane Chu <7559015+janechu@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:15:49 -0700 Subject: [PATCH 1/2] Update typescript skill file and fast element design doc --- .github/skills/typescript/SKILL.md | 49 ++++++++++++++++++------------ packages/fast-element/DESIGN.md | 4 +-- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/.github/skills/typescript/SKILL.md b/.github/skills/typescript/SKILL.md index a72686fecf8..4a46ee4ebe0 100644 --- a/.github/skills/typescript/SKILL.md +++ b/.github/skills/typescript/SKILL.md @@ -20,12 +20,39 @@ Sub-entry-points expose focused APIs through the `exports` map: ```ts import { twoWay } from "@microsoft/fast-element/two-way.js"; import { reactive } from "@microsoft/fast-element/state.js"; -import { composedParent } from "@microsoft/fast-element/utilities.js"; ``` The barrel `index.ts` explicitly lists every re-export grouped by subsystem — no `export *` statements. +Aside from the `index.ts` or `index.*.ts` files there should be no barrel exports. + +## Side Effects + +Do not add side effectful code and do not add `sideEffects` to `package.json` files. +APIs added should import named exports. + +## Browser APIs + +### Do not use + +Our stance as a framework library is that certain browser APIs are best avoided by +the framework. We may facilitate the use of them through our provided APIs. + +List of APIs to avoid implementing in FAST packages: +- `requestIdleCallback` +- `setTimeout` +- `setInterval` + +### Avoid + +Some browser APIs can be used but should be avoided as a developer may encounter +edge cases with task queuing or other logic their app is executing. + +List of APIs to avoid in FAST packages: +- `requestAnimationFrame` +- `queueMicrotask` + ## Custom elements Elements extend `FASTElement`. Do **not** use the `@customElement` decorator. @@ -33,6 +60,7 @@ Elements extend `FASTElement`. Do **not** use the `@customElement` decorator. Use `define()` for registration. `define()` returns a `Promise` that resolves immediately when a template is provided: +Example define.ts (side-effect import): ```ts export class MyElement extends FASTElement { @observable items: string[] = []; @@ -45,22 +73,6 @@ await MyElement.define({ }); ``` -Use `compose()` when registration should be deferred — downstream libraries like Fluent -Web Components use this pattern with a design-system registry. `compose()` returns a -`Promise` that always resolves immediately: - -```ts -// my-element.definition.ts -export const definition = await MyElement.compose({ - name: "my-element", - template, - styles, -}); - -// define.ts (side-effect import) -definition.define(); -``` - ## Templates Templates use the `html` tagged template literal typed to the element class: @@ -255,8 +267,7 @@ methods use `typeof` to carry overloaded signatures: export const FASTElement: { new (): FASTElement; define: typeof define; - compose: typeof compose; -} = Object.assign(createFASTElement(HTMLElement), { define, compose }); +} = Object.assign(createFASTElement(HTMLElement), { define }); ``` ### Tagged template intersection types diff --git a/packages/fast-element/DESIGN.md b/packages/fast-element/DESIGN.md index 96a7d10b3b2..b59082f2f61 100644 --- a/packages/fast-element/DESIGN.md +++ b/packages/fast-element/DESIGN.md @@ -176,7 +176,7 @@ logging, telemetry, or a devtools panel. - `onAttributeChangedCallback()` is the standard handler that processes attribute changes. During the prerendered bind, it is temporarily swapped to a no-op (see above) to avoid redundant processing of server-rendered attribute values. - Exposes `addBehavior` / `removeBehavior` for dynamic `HostBehavior` management (used by `ElementStyles`). -`FASTElementDefinition` wraps all the metadata for a custom element class: its tag name, template, styles, and observed attribute list. It is created by subclass `define()` calls or directly with `FASTElementDefinition.compose()` (which returns `Promise`, always resolving immediately) and registered globally via `fastElementRegistry`. Consumers that need focused access to definition lookup can import `fastElementRegistry` from `@microsoft/fast-element/registry.js`; `fastElementRegistry.whenRegistered(tagName)` resolves with the matching definition once that tag name is registered. `PartialFASTElementDefinition.template` may be either a concrete `ElementViewTemplate>` or a `FASTElementTemplateResolver` function that receives the composed definition and returns the concrete template (sync or async). `FASTElementDefinition.template` always stores the concrete `ElementViewTemplate>` after composition or resolver settlement. The subclass static `define()` method returns `Promise` — resolving immediately for complete definitions or definitions without an initial template, and resolving async template resolver functions only after extensions have had a chance to update the definition. +`FASTElementDefinition` wraps all the metadata for a custom element class: its tag name, template, styles, and observed attribute list. It is created by subclass `define()` calls and registered globally via `fastElementRegistry`. Consumers that need focused access to definition lookup can import `fastElementRegistry` from `@microsoft/fast-element/registry.js`; `fastElementRegistry.whenRegistered(tagName)` resolves with the matching definition once that tag name is registered. `PartialFASTElementDefinition.template` may be either a concrete `ElementViewTemplate>` or a `FASTElementTemplateResolver` function that receives the composed definition and returns the concrete template (sync or async). `FASTElementDefinition.template` always stores the concrete `ElementViewTemplate>` after composition or resolver settlement. The subclass static `define()` method returns `Promise` — resolving immediately for complete definitions or definitions without an initial template, and resolving async template resolver functions only after extensions have had a chance to update the definition. #### Extensions @@ -621,7 +621,7 @@ Below is a conceptual map of the major subsystems and their relationships: **Authoring flow summary**: 1. Developer writes a class extending `FASTElement`, decorates properties with `@observable` / `@attr`, and calls `MyElement.define({ name, template, styles })`. -2. `MyElement.define` → `FASTElementDefinition.compose(...).define()` registers the element with the Custom Element Registry. +2. `MyElement.define` registers the element with the Custom Element Registry. 3. When the browser upgrades the element, `ElementController.forCustomElement(element)` is called in the constructor. 4. On `connectedCallback`, the controller renders the template into the shadow root. If the element already has a shadow root from SSR (prerendered content) and hydration has been enabled via `enableHydration()`, the installed hydration hook uses `template.hydrate()` to map existing DOM nodes to binding targets instead of cloning new DOM. If no template is available yet, the element connects without rendering until a later `definition.template` update recreates the controller. Compilation is lazy: the first render call triggers `Compiler.compile()`, subsequent calls clone the already-compiled `DocumentFragment`. 5. `HTMLView.bind(source)` wires up each `ViewBehavior`. `oneWay` bindings create `ExpressionNotifier`s that track observable dependencies automatically. From fe576028a8f3b3d3988e0314736c08a8506edc20 Mon Sep 17 00:00:00 2001 From: Jane Chu <7559015+janechu@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:16:03 -0700 Subject: [PATCH 2/2] Change files --- ...-fast-element-5290546b-2479-4c8a-bd1b-dc20ef1d6f31.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@microsoft-fast-element-5290546b-2479-4c8a-bd1b-dc20ef1d6f31.json diff --git a/change/@microsoft-fast-element-5290546b-2479-4c8a-bd1b-dc20ef1d6f31.json b/change/@microsoft-fast-element-5290546b-2479-4c8a-bd1b-dc20ef1d6f31.json new file mode 100644 index 00000000000..aa9743ab4d8 --- /dev/null +++ b/change/@microsoft-fast-element-5290546b-2479-4c8a-bd1b-dc20ef1d6f31.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Update typescript skill file and fast element design doc", + "packageName": "@microsoft/fast-element", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +}