Boost Front‑End Component Design: Usability, Extensibility, and Best Practices

This article explains why front‑end component design matters and provides practical guidance on improving component usability, choosing between slots and props, writing standardized APIs, and achieving high extensibility through techniques like DOM hand‑off and headless UI patterns.

ELab Team
ELab Team
ELab Team
Boost Front‑End Component Design: Usability, Extensibility, and Best Practices

Why Design Front‑End Components?

Unlike back‑end code that only handles data, front‑end code must render UI, process data, and call APIs. With the evolution of ES6 classes, React functional components, and Vue templates, front‑end code has shifted from flat scripts to hierarchical, object‑oriented structures, making component design a hot topic.

Components are defined as independently functional software entities with contract‑specified interfaces, clear context dependencies, and the ability to be deployed and assembled. Good component design reduces complexity, improves maintainability, and enhances reusability.

How to Improve Component Usability?

Reasonable Component Encapsulation

A component should be neither the whole page nor an overly tiny UI fragment. Classify components as container, functional, or presentation components, ensuring functional cohesion, consistent styling, and communication with parent elements only via props.

Encapsulation granularity should be based on the component’s purpose, not merely the number of features. Examples include InputTag, InputNumber, AutoComplete, and Mentions, which combine specific functionalities into single reusable components.

When a component contains sub‑components that can be used independently, expose them as internal components (e.g., Image.Preview, Image.PreviewGroup) with APIs such as srcList, visible, actions, and scales.

Standardized API Writing

Minimize required API fields and provide sensible defaults.

Use clear, meaningful names (e.g., onXXX, renderXXX, beforeXXX/afterXXX, xxxProps).

Prefer common words like value, visible, size, disabled, label, type.

Maintain separate type definition files and include them in the component package for real‑time type hints.

Add comments to API definitions.

[Slot] vs [Props] Choice

Problems with Props

Complex UI components often require many props, making the API cumbersome. Using slots (or internal components) can simplify composition and improve readability.

export type CardProps = {<br/>  infoProps?: { title?: ReactNode; content?: ReactNode; };<br/>  moreInfoProps?: { info?: ReactNode; triggerProps?: TriggerProps; descriptionsProps?: DescriptionsProps; };<br/>  className?: string;<br/>  style?: CSSStyleSheet;<br/>  width?: number | string;<br/>  imageProps?: {<br/>    srcList?: Array<SrcList>;<br/>    afterImgs?: ReactNode;<br/>    aspectRatio?: string;<br/>    buttonProps?: ButtonProps;<br/>    current?: number;<br/>    defaultCurrent?: number;<br/>    onChangeCurrent?: (current: number) => undefined;<br/>    PreviewGroupProps?: ImagePreviewGroupProps;<br/>    src?: string;<br/>  };<br/>  children?: ReactNode;<br/>} & CardCheckboxProps;

Refactoring with slots yields a clearer structure:

<Card type="verticle" {...cardProps}><br/>  <CardImage {...ImageProps} /><br/>  <CardContent {...InfoProps}><br/>    <div className="card-title">title</div><br/>    <div className="card-content">content</div><br/>    <Tag>Tag</Tag><br/>  </CardContent><br/>  <CardTrigger {...triggerProps}><br/>    <Description {...descriptionProps} /><br/>  </CardTrigger><br/></Card>

What is a Slot?

Slots, introduced by Vue, act as placeholders that can be filled by other components, enabling parent‑to‑child content distribution.

How to Enhance Component Extensibility?

Give DOM Control to Users

Expose APIs that let developers inject custom DOM or logic. For example, the Cascader component adds a dropdownRender prop that receives a function returning a ReactNode to render additional footer content.

<Cascader<br/>  options={options}<br/>  dropdownRender={(menu) => (<br/>    <div><br/>      {menu}<br/>      <Divider style={{ margin: 0 }} /><br/>      <div style={{ margin: 4 }}>The footer content</div><br/>    </div><br/>  )}<br/>/>

Similar extensibility hooks include renderFooter, renderOption, and renderFormat, which hand over rendering control to the component user.

Design Extensible APIs

Start with a clear functional scope, then evolve the API. A mobile selector initially defined as:

type PickerProps {<br/>  dataSource?: PickerData[] | PickerData[][];<br/>  multiple?: boolean;<br/>  time?: boolean;<br/>  value?: (string|number)[];<br/>  onChange?: (value: (string|number)[]) => void;<br/>  ...<br/>}

Later, to support region and cascader selections, replace multiple boolean flags with a single type enum:

type PickerProps {<br/>  dataSource?: PickerData[] | PickerData[][];<br/>  type?: "single" | "multiple" | "cascader" | "region" | "time";<br/>  value?: (string|number)[];<br/>  onChange?: (value: (string|number)[]) => void;<br/>  ...<br/>}

Generics and optional types can further extend APIs, as seen in Table pagination or border configurations.

Ultimate Extensibility – Headless UI

Headless UI separates component state/logic from presentation, allowing developers to apply any styling or layout. Implementations include atomic sub‑components or hook‑based APIs that expose interaction props for arbitrary UI wrappers.

<NumberInput><br/>  <NumberInputField /><br/>  <NumberInputStepper><br/>    <NumberIncrementStepper /><br/>    <NumberDecrementStepper /><br/>  </NumberInputStepper><br/></NumberInput>
function HookUsage() {<br/>  const { getInputProps, getIncrementButtonProps, getDecrementButtonProps } =<br/>    useNumberInput({ step: 0.01, defaultValue: 1.53, min: 1, max: 6, precision: 2 });<br/><br/>  const inc = getIncrementButtonProps();<br/>  const dec = getDecrementButtonProps();<br/>  const input = getInputProps();<br/><br/>  return (<br/>    <HStack maxW='320px'><br/>      <Button {...inc}>+</Button><br/>      <Input {...input} /><br/>      <Button {...dec}>-</Button><br/>    </HStack><br/>  );<br/>}

While powerful, headless components require more design effort and are best suited for cross‑project or cross‑platform reusable libraries.

frontendAPIComponent DesignextensibilitySlotusabilityheadless UI
ELab Team
Written by

ELab Team

Sharing fresh technical insights

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.