Best Practices
While Radiant is designed for flexibility, following these best practices will lead to more maintainable and reliable component libraries.
Naming Custom Elements
Custom element names must follow these browser-enforced rules:
- Must contain a hyphen (
-) to avoid conflicts with standard HTML elements. - Must start with a lowercase letter.
- Cannot start with a hyphen.
- Cannot contain uppercase letters.
// ✅ Valid names
@customElement('user-card')
@customElement('my-app-button')
// ❌ Invalid names
@customElement('usercard') // Missing hyphen
@customElement('User-Card') // Contains uppercase
Recommendation: Namespace Your Components
To avoid tag name collisions, especially if you're building a library, use a consistent prefix.
@customElement('acme-button')
@customElement('acme-card')
Component Design
One Component Per File
For better organization and ease of navigation, define only one custom element per file.
Export Your Class
Always export the component class. This is crucial for:
- Testing the component in isolation.
- Type checking when using the component in other TypeScript files.
Use Descriptive Names
Use clear, descriptive names. Avoid generic names like my-component or custom-element.
Typing Components
Type safety is a core feature of Radiant. We recommend following these patterns to ensure your components are correctly typed for both TypeScript and JSX integration.
Defining Props
Define a separate type for your component's public properties. This type can be shared between the component script and the JSX template.
export type UserCardProps = {
name?: string;
avatarUrl?: string;
isAdmin?: boolean;
};
@customElement('user-card')
export class UserCard extends RadiantElement {
@reactiveProp({ type: String }) declare name: string;
@reactiveProp({ type: String }) declare avatarUrl: string;
@reactiveProp({ type: Boolean }) declare isAdmin: boolean;
}
JSX Integration (Kita)
To enable type checking for your custom element in JSX templates (using Kita), register it in the JSX.IntrinsicElements interface.
declare global {
namespace JSX {
interface IntrinsicElements {
'user-card': HtmlTag & UserCardProps;
}
}
}
Technical Tips
Registration Timing
Custom elements are registered immediately when the file is evaluated. If you import a file containing a @customElement decorator, the element is ready for use in the DOM.
Reactive State Mutation (Reference Equality)
Radiant uses reference equality to detect changes in reactive properties and fields.
// ❌ Won't trigger update (same reference)
this.items.push('new item');
// ✅ Triggers update (new reference)
this.items = [...this.items, 'new item'];
Prefer autonomous elements over customized built-ins
While Radiant supports extending built-in elements (e.g., extends: 'button'), browser support for customized built-in elements is limited.