con un clic
add-component-property
// Add a reactive property to an existing Lit web component with proper decorators, types, tests, and documentation
// Add a reactive property to an existing Lit web component with proper decorators, types, tests, and documentation
Identify and select the right Ignite UI Web Components for your app UI, then navigate to official docs, usage examples, and API references
Implement application views from design images using Ignite UI Web Components. Uses MCP servers (igniteui-cli, igniteui-theming) to discover components, generate themes, and follow best practices. Triggers when the user provides a design image (screenshot, mockup, wireframe) and wants it built as a working view with Ignite UI Web Components. Also triggers when the user asks to "implement this design", "build this UI", "convert this mockup", or "create a page from this image" in an Ignite UI Web Components project.
Integrate Ignite UI Web Components packages into React, Angular, Vue, or vanilla JS applications with framework-specific configurations
Customize Ignite UI Web Components styling using CSS custom properties, optional Sass, and the igniteui-theming MCP server for AI-assisted theming
Optimize application bundle size by importing only necessary components and using tree-shaking effectively
Create a new Lit web component following project conventions, including component class, styles, tests, Storybook story, and proper exports
| name | add-component-property |
| description | Add a reactive property to an existing Lit web component with proper decorators, types, tests, and documentation |
This skill guides you through adding a new reactive property to an existing Lit web component.
Gather or confirm:
Add the property with appropriate decorator to the component class:
For primitive types (reflect to attribute):
/**
* [Property description]
* @attr [attribute-name]
* @default [default-value]
*/
@property({ reflect: true })
public propertyName: PropertyType = defaultValue;
For readonly properties:
/**
* [Property description - read-only]
*/
@property({ attribute: false })
public readonly readonlyProp: PropertyType = defaultValue;
For boolean types:
/**
* [Property description]
* @attr [attribute-name]
* @default false
*/
@property({ type: Boolean, reflect: true })
public propertyName = false;
For number types:
/**
* [Property description]
* @attr [attribute-name]
*/
@property({ type: Number, reflect: true })
public propertyName = 0;
For complex types (no reflection):
/**
* [Property description]
*/
@property({ attribute: false })
public propertyName: ComplexType = defaultValue;
If the property affects rendering, update the render() method:
protected override render() {
return html`
<div part="base" class=${this.propertyName}>
<!-- Updated template using new property -->
</div>
`;
}
If the property requires side effects or needs to sync computed/dependent properties, use Lit's lifecycle hooks.
Preferred: Use update() hook (DOM is available, best for side effects):
protected override update(changedProperties: PropertyValues<this>): void {
if (changedProperties.has('propertyName')) {
// Handle property change with DOM access
// Update dependent properties or trigger side effects
// Example: Update ARIA attributes, sync internal state, etc.
}
super.update(changedProperties);
}
If absolutely needed: Use willUpdate() (before render, no DOM access):
protected override willUpdate(changedProperties: PropertyValues<this>): void {
if (changedProperties.has('propertyName')) {
// Handle property change before rendering
// Use only if you need to compute values before render
// No DOM access available here
}
}
Best Practices:
update() for most cases - DOM is available for queries and side effectswillUpdate() only when you need to compute derived state before renderingsuper.update(changedProperties) when overriding update()changedProperties.has() to avoid unnecessary workAdd tests for the new property in [component-name].spec.ts:
it('should have correct default value', async () => {
const el = await fixture<IgcComponentComponent>(
html`<igc-component></igc-component>`
);
expect(el.propertyName).to.equal(defaultValue);
});
it('can change property', 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 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);
});
Add the property to stories/[component-name].stories.ts:
Update argTypes:
argTypes: {
propertyName: {
type: 'string', // or 'boolean', 'number'
description: '[Property description]',
control: 'text', // or 'boolean', 'number', 'select'
table: { defaultValue: { summary: 'defaultValue' } },
},
// ... other properties
}
Update args:
args: {
propertyName: defaultValue,
// ... other properties
}
Update interface:
interface IgcComponentArgs {
/** [Property description] */
propertyName: PropertyType;
// ... other properties
}
Update story template:
export const Basic: Story = {
render: (args) => html`
<igc-component .propertyName=${args.propertyName}> Content </igc-component>
`,
};
Run tests and verify in Storybook:
# Run tests
npm run test
# Check that the project will transpile
npm run check-types
# Start Storybook
npm run storybook
@property decorator@attr for primitivesreflect: true only for primitivesProblem: Trying to reflect objects/arrays to attributes
Solution: Use attribute: false for complex types
Problem: camelCase not mapping to kebab-case
Solution: Lit auto-converts, or specify explicitly: @property({ attribute: 'custom-name' })
Problem: Boolean/number properties not converting from string attributes
Solution: Use { type: Boolean } or { type: Number } in decorator
Problem: New property not controllable in Storybook Solution: Add to argTypes, args, interface, and template
See src/components/badge/badge.ts for examples of:
variantoutlinedshape