Core Principles

When building modern UI components, it's important to keep these core principles in mind.

Composability and Reusability

Favor composition over inheritance – build components that can be combined and nested to create more complex UIs, rather than relying on deep class hierarchies.

Composable components expose a clear API (via props/slots) that allows developers to customize behavior and appearance by plugging in child elements or callbacks.

This makes components highly reusable in different contexts. (React’s design reinforces this: “Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way.”)

Accessible by Default

Components must be usable by all users. Use semantic HTML elements appropriate to the component’s role (e.g. <button> for clickable actions, <ul>/<li> for lists, etc.) and augment with WAI-ARIA attributes when necessary.

Ensure keyboard navigation and focus management are supported (for example, arrow-key navigation in menus, focus traps in modals). Each component should adhere to accessibility standards and guidelines out of the box.

This means providing proper ARIA roles/states and testing with screen readers. Accessibility is not optional – it’s a baseline feature of every component.

Customizability and Theming

A component should be easy to restyle or adapt to different design requirements. Avoid hard-coding visual styles that cannot be overridden.

Provide mechanisms for theming and styling, such as CSS variables, clearly documented class names, or style props. Ideally, components come with sensible default styling but allow developers to customize appearance with minimal effort (for example, by passing a className or using design tokens).

This principle ensures components can fit into any brand or design system without “fighting” against default styles.

Lightweight and Performant

Components should be as lean as possible in terms of assets and dependencies. Avoid bloating a component with large library dependencies or overly complex logic, especially if that logic isn’t always needed.

Strive for good performance (both rendering and interaction) by minimizing unnecessary re-renders and using efficient algorithms for heavy tasks. If a component is data-intensive (like a large list or table), consider patterns like virtualization or incremental rendering, but keep such features optional.

Lightweight components are easier to maintain and faster for end users.

Transparency and Code Ownership

In open-source, consumers often benefit from having full visibility and control of component code. This spec encourages an “open-source first” mindset: components should not be black boxes.

When developers import or copy your component, they should be able to inspect how it works and modify it if needed. This principle underlies the emerging “copy-and-paste” distribution model (discussed later) where developers integrate component code directly into their projects.

By giving users ownership of the code, you increase trust and allow deeper customization.

Even if you distribute via a package, embrace transparency by providing source maps, readable code, and thorough documentation.

Well-documented and DX-Friendly

A great component is not just code – it comes with clear documentation and examples. From a developer experience (DX) perspective, your components should be easy to learn and integrate.

Document each component’s purpose, props, and usage examples. Include notes on accessibility (like keyboard controls or ARIA attributes used) and any customization options.

Good documentation reduces misuse and lowers the barrier for adoption. We will cover documentation expectations in the Publish section, but it’s listed here as a principle because planning for good documentation and DX should happen during the design/build phase.