| name | tonic-ui-types |
| description | Use this skill when adding JSDoc type definitions to React components in Tonic UI. Triggers include "add type definitions", "add JSDoc types", "document component props", or when creating new components that need type annotations. |
Add Type Definitions to React Components
This skill provides guidelines for adding JSDoc type definitions to React components in the Tonic UI design system.
Overview
Tonic UI uses JSDoc annotations (@typedef and @type) to provide type information for React components. This enables better IDE support, documentation generation, and type checking.
Prerequisites
Before adding type definitions:
- Read the component documentation (required) - Check
packages/react-docs/pages/components/[component-name]/index.page.mdx
- Locate the Props table in the
## Props section
- Document all prop names, types, defaults, and descriptions
- Use exact descriptions from the documentation
- If no documentation exists, analyze the component implementation
- Read the component file to understand its implementation
- Verify the component pattern (forwardRef vs functional component)
- Identify the HTML element type that the component renders
Required Workflow
Step 1: Identify the Component Pattern
Determine which pattern the component uses:
ForwardRef Component (most common):
const Component = forwardRef((inProps, ref) => { ... });
Functional Component (no ref):
const Component = (inProps) => { ... };
Step 2: Add the @typedef Block
Add a JSDoc @typedef block before the component declaration. Include all custom props with their types and descriptions.
Format:
Property Type Examples:
{React.ReactNode} - React children or renderable content
{boolean} - Boolean flags
{string} - String values
{number} - Numeric values
{function} - Callback functions
{'option1' | 'option2'} - String enums
{'sm' | 'md' | 'lg'} - Size variants
{React.ReactNode | React.ReactNode[]} - Single or array
{React.RefObject<HTMLElement>} - Ref objects
Step 3: Add the @type Annotation
Add a @type annotation immediately before the component declaration.
For ForwardRef Components (simple — no prop conflicts):
const Component = forwardRef((inProps, ref) => {
For ForwardRef Components (with prop conflicts — use Omit):
When the component defines custom props that conflict with native HTML element props (e.g., onChange, onBlur, children, size), use Omit<> to exclude the conflicting native props:
const Component = forwardRef((inProps, ref) => {
Common conflicts to Omit:
| Custom prop | Conflicts with native | Example components |
|---|
children (render prop) | React.ReactNode children | Accordion, Modal |
onChange (custom signature) | HTMLElement.onChange | Checkbox, Switch, Tabs |
onBlur, onFocus, onClick | Native event handlers | Checkbox, Switch |
size (string enum) | HTMLInputElement.size (number) | Input |
For Functional Components:
const Component = (inProps) => {
Step 4: Choose the Correct HTML Element
Match the element type to what the component renders:
| Component renders | Use element | Ref type |
|---|
<button> | 'button' | HTMLButtonElement |
<input> | 'input' | HTMLInputElement |
<a> | 'a' | HTMLAnchorElement |
<label> | 'label' | HTMLLabelElement |
<div> (default) | 'div' | HTMLDivElement |
<span> | 'span' | HTMLSpanElement |
Step 4.5: Add Type Test File
Create a type test file at packages/react/__type-tests__/components/{component-name}.test-d.tsx to verify the type definitions compile correctly.
Format:
import React, { createRef } from 'react';
import { ComponentName } from '@tonic-ui/react';
<ComponentName>content</ComponentName>;
<ComponentName propName="value" />;
const ref = createRef<HTMLDivElement>();
<ComponentName ref={ref} />;
<ComponentName mt={2} px="4x" />;
The type tests are compiled with tsconfig.json in the __type-tests__/ directory using strict: true and noEmit: true — they only need to compile without errors.
Implementation Rules
- Copy descriptions exactly - Use the exact wording from the Props table in the documentation
- Always include
StyleProps - All Tonic UI components support style props
- Use brackets for optional props -
[propName] indicates optional
- Document defaults - Use
[propName=default] syntax
- Match documentation exactly - Props, types, defaults, and descriptions must match the docs table
- Use proper React types -
React.ReactNode, React.RefObject, etc.
- Check for prop conflicts - If a custom prop name collides with a native HTML prop, use
Omit<> in the @type annotation
- Align with
useDefaultProps - Verify that default values in @typedef match the defaults provided by useDefaultProps
Examples
Example 1: Simple Component with Few Props
const Link = forwardRef((inProps, ref) => {
Example 2: Component with Enum Props
const Button = forwardRef((inProps, ref) => {
Example 3: Component with Prop Conflicts (Omit pattern)
const Checkbox = forwardRef((inProps, ref) => {
Example 4: Component with Complex Props
const Modal = forwardRef((inProps, ref) => {
Reference Files
Well-documented components to use as reference:
packages/react/src/link/Link.js - Simple component, no Omit needed
packages/react/src/button/Button.js - Basic component with size/variant
packages/react/src/input/Input.js - Uses Omit<..., 'size'> for prop conflict
packages/react/src/checkbox/Checkbox.js - Uses Omit<..., 'onBlur' | 'onChange' | 'onClick' | 'onFocus'>
packages/react/src/accordion/Accordion.js - Uses Omit<..., 'children'> for render prop
packages/react/src/tabs/Tabs.js - Uses Omit<..., 'onChange'> for custom handler
Best Practices
- Follow existing patterns - Match the style of nearby components
- Test in IDE - Verify that autocomplete works after adding types
- Keep in sync - Update types when props change
- Document all public props - Even if the description is just
-
Common Issues and Solutions
Issue: IDE doesn't recognize custom props
Solution: Ensure the @typedef is directly above the @type annotation
Issue: Native HTML props not showing
Solution: Add React.ComponentPropsWithoutRef<'element'> to the type union
Issue: Ref type mismatch
Solution: Match React.RefAttributes<HTMLElement> to the actual DOM element type