Agent Skills › IgniteUI/igniteui-webcomponents › add-component-property

add-component-property

GitHub

为现有 Lit Web Component 添加响应式属性,涵盖装饰器、类型定义、测试、规范更新及文档生成。

.github/skills/add-component-property/SKILL.md IgniteUI/igniteui-webcomponents

Trigger Scenarios

为组件添加新属性 修改组件属性配置

Install

npx skills add IgniteUI/igniteui-webcomponents --skill add-component-property -g -y
More Options

Non-standard path

npx skills add https://github.com/IgniteUI/igniteui-webcomponents/tree/master/.github/skills/add-component-property -g -y

Use without installing

npx skills use IgniteUI/igniteui-webcomponents@add-component-property

指定 Agent (Claude Code)

npx skills add IgniteUI/igniteui-webcomponents --skill add-component-property -a claude-code -g -y

安装 repo 全部 skill

npx skills add IgniteUI/igniteui-webcomponents --all -g -y

预览 repo 内 skill

npx skills add IgniteUI/igniteui-webcomponents --list

SKILL.md

Frontmatter
{
    "name": "add-component-property",
    "description": "Add a reactive property to an existing Lit web component with proper decorators, types, tests, specification updates, and documentation"
}

Add Component Property

Adds a reactive property to an existing component, with the documentation, tests, specification update and generated metadata that go with it.

When to Use

  • "Add an 'orientation' property to the divider component"
  • "Add a 'variant' property with multiple options"

Related Skills

Required Context

  • Component: which component to modify
  • Name and type: camelCase property, kebab-case attribute
  • Default value: booleans must default to false
  • Reflection: only for primitives that affect styling or accessibility
  • Purpose: the description that ships in the public API docs

Steps

1. Declare the property

Place it in the //#region Public attributes and properties section, in the shape that matches its type:

/**
 * The style variant of the component.
 * @attr variant
 * @default 'primary'
 */
@property({ reflect: true })
public variant: StyleVariant = 'primary';

/**
 * Whether user interaction with the component is disabled.
 * @attr
 * @default false
 */
@property({ type: Boolean, reflect: true })
public disabled = false;

/**
 * The number of items rendered per page.
 * @attr items-per-page
 * @default 10
 */
@property({ type: Number, attribute: 'items-per-page' })
public itemsPerPage = 10;

/** The items rendered by the component. */
@property({ attribute: false })
public items: Array<Item> = [];

Rules that are easy to get wrong:

  • Booleans must default to false. An attribute's presence equates to true, so a true default cannot be turned off from markup. Rename the property instead (enabled → disabled).
  • Never reflect objects or arrays, and give them attribute: false so Lit doesn't try to serialize them.
  • Lit derives the attribute name automatically, but spell it out for multi-word properties and for HTML look-alikes (readOnly → readonly, minLength → minlength).
  • A read-only value is a getter, not a readonly @property.

2. Write the description

The JSDoc is copied verbatim into custom-elements.json, the generated Storybook metadata and the Angular / React / Blazor wrapper docs.

  • No igc- tag names in prose — "the select component", not igc-select.
  • Don't restate that it is an attribute. @attr already says so.
  • No Gets/Sets. State what the value is; add a second sentence for side effects.
  • Booleans start with "Whether …" and must describe the true state accurately — verify against the implementation, since hide*/disable* names invert the sentence.
  • Present tense, not "will".
// ❌ Wrong
/**
 * The outlined attribute of the control.
 * @attr
 */

// ✅ Right
/**
 * Whether the control has an outlined appearance.
 * @attr
 */

Full reference: create-new-component → Documentation Conventions.

3. React to the change

If the property only affects the template, do nothing — just use it in render(). If it has side effects or feeds derived state, use the Lit lifecycle hooks, not @watch:

// Derived state, before rendering
protected override willUpdate(changedProperties: PropertyValues<this>): void {
  if (changedProperties.has('value')) {
    this._normalized = this.value.trim();
  }
}

// Side effects that need DOM access
protected override update(changedProperties: PropertyValues<this>): void {
  if (changedProperties.has('disabled')) {
    this._internals.setARIA({ ariaDisabled: `${this.disabled}` });
  }
  super.update(changedProperties);
}

Always guard with changedProperties.has() and call super.update() when overriding update.

For a form-associated control, a property that participates in constraint validation (min, pattern, maxLength, …) must call this._validate() from its setter.

4. Add tests

it('is initialized with the proper default value', async () => {
  const el = await fixture<IgcComponentComponent>(
    html`<igc-component></igc-component>`
  );

  expect(el.propertyName).to.equal(defaultValue);
});

it('updates on property change', async () => {
  const el = await fixture<IgcComponentComponent>(
    html`<igc-component></igc-component>`
  );

  el.propertyName = newValue;
  await elementUpdated(el);

  expect(el.propertyName).to.equal(newValue);
});

it('reflects to an attribute', async () => {
  const el = await fixture<IgcComponentComponent>(
    html`<igc-component property-name=${value}></igc-component>`
  );

  expect(el.propertyName).to.equal(value);
  expect(el.getAttribute('property-name')).to.equal(value);
});

If the property changes the rendered semantics, extend the a11y audit rather than adding a separate one.

5. Update the specification

A new property is a change to the public API, so src/components/[name]/spec.md changes with it. The property is not done until the spec describes it. The full rules are in Specifications.

Always:

  • Add a row to ### Properties and attributes with the name, the attribute, whether it reflects, the type, the default and the same description as the JSDoc.
  • Add the scenarios you wrote in step 4 to ## Test scenarios, in the subsection matching the describe block they live in, and renumber the items after them so the numbering stays contiguous.
  • Bump ## Revision history with a new row: the next version, today's date, and what changed.

When applicable:

  • A property that adds a keyboard interaction updates ### Keyboard interactions and ### Keyboard support.
  • A property that changes the roles or the ARIA state updates ### ARIA roles and properties.
  • A property that introduces a behavior worth calling out gets a subsection under ### Developer experience, with a short example.
  • A property that is localizable updates ### Localization.
  • A constraint the property brings — a value it clamps, a mode it is ignored in — belongs in ## Assumptions and limitations.

Every heading you add needs a matching entry in the table of contents at the top of the file.

Deprecating or removing a property is the same exercise in reverse: keep the row, mark it deprecated with the version and the replacement, and record it in the revision history.

6. Regenerate the story metadata

The argTypes, args and the args interface live inside a generated // region default … // endregion block in stories/[component-name].stories.ts. Never edit it by hand:

npm run cem        # custom-elements.json from the source JSDoc
npm run build:meta # the `// region default` block of each story

If the generated description reads badly, fix the JSDoc and regenerate. If the property doesn't appear at all, the story was skipped: the filename must match the tag name (igc-date-picker → date-picker.stories.ts) and the region fence must be present — a missing fence is a silent no-op.

Then wire the property into the story templates, which are hand-written:

export const Basic: Story = {
  render: (args) => html`
    <igc-component .propertyName=${args.propertyName}>Content</igc-component>
  `,
};

7. Verify

npm run check
npm run test

Validation Checklist

  • Property declared in the public properties region with the right decorator options
  • Booleans default to false; complex types use attribute: false
  • @attr and @default tags present; description follows the description rules
  • Lifecycle hook used for side effects, super.update() called
  • _validate() called from setters affecting constraint validation
  • Tests cover default, change and reflection
  • spec.md updated: API table row, test scenarios renumbered, revision history bumped, and the keyboard / ARIA / limitations sections touched if the property affects them
  • npm run cem && npm run build:meta run; generated story region committed
  • Story template uses the new property
  • npm run check and npm run test pass
  • CHANGELOG updated if the property is part of a feature or fix

Common Pitfalls

Symptom Cause / Fix
Attribute can't be turned off from markup Boolean defaults to true — rename so the default is false
[object Object] in the DOM Complex type without attribute: false
String 'false' behaves as true Missing { type: Boolean } in the decorator
Attribute name is propertyname Multi-word property without an explicit attribute: 'property-name'
Story control missing after adding a property npm run build:meta not run, or the story is being skipped silently
Story description reverts The generated region was hand-edited — fix the JSDoc instead
Spec and implementation disagree The property was shipped without updating spec.md — the spec is part of the change
Spec test numbering jumps Scenarios inserted without renumbering the ones after them

Reference Examples

  • src/components/badge/badge.ts — reflected string, boolean and union-typed properties
  • src/components/input/input.ts — validation-affecting setters calling _validate()
  • src/components/combo/combo.ts — complex, non-attribute properties
  • src/components/badge/spec.md — a compact spec whose API tables track the properties above

Version History

  • 7.3.2 Current 2026-09-23 01:52

    将内联组件规范整合到项目结构中,从 Wiki 迁移表单、日期选择器等规范至 spec.md 文件。

  • 7.2.4 2026-08-20 11:42

Same Skill Collection

.agents/skills/add-component-property/SKILL.md
.agents/skills/create-new-component/SKILL.md
.agents/skills/review-component-pr/SKILL.md
.agents/skills/update-component-styles/SKILL.md
.github/skills/create-new-component/SKILL.md
.github/skills/review-component-pr/SKILL.md
.github/skills/update-component-styles/SKILL.md
.agents/skills/skill-authoring/SKILL.md
skills/igniteui-wc-choose-components/SKILL.md
skills/igniteui-wc-customize-component-theme/SKILL.md
skills/igniteui-wc-figma-to-app/SKILL.md
skills/igniteui-wc-generate-from-image-design/SKILL.md
skills/igniteui-wc-grids/SKILL.md
skills/igniteui-wc-integrate-with-framework/SKILL.md
skills/igniteui-wc-migrate-grid-lite-to-premium/SKILL.md
skills/igniteui-wc-optimize-bundle-size/SKILL.md

Metadata

Files
0
Version
7.3.2
Hash
ae42d347
Indexed
2026-08-20 11:42

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-30 13:08
浙ICP备14020137号-1