Skip to main content

Overview

The Natura Design System provides full TypeScript support with comprehensive type definitions for all components, props, and APIs. This guide covers best practices for using the library in TypeScript projects.

Installation

TypeScript definitions are included with the package:
npm install @naturacosmeticos/natds-react
No need to install @types packages - TypeScript definitions are bundled.

Basic Component Usage

Importing Components

import { Button, TextField, Card } from '@naturacosmeticos/natds-react';
import type { ButtonProps } from '@naturacosmeticos/natds-react';

Using Component Props

import { Button } from '@naturacosmeticos/natds-react';

function MyButton() {
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    console.log('Button clicked', event);
  };

  return (
    <Button
      variant="contained"
      color="primary"
      onClick={handleClick}
    >
      Click me
    </Button>
  );
}

Type-Safe Prop Spreading

import type { IButtonProps } from '@naturacosmeticos/natds-web';

interface CustomButtonProps extends IButtonProps {
  label: string;
  loading?: boolean;
}

function CustomButton({ label, loading, ...buttonProps }: CustomButtonProps) {
  return (
    <Button disabled={loading} {...buttonProps}>
      {loading ? 'Loading...' : label}
    </Button>
  );
}

Component Prop Interfaces

All components export their prop interfaces:
import type {
  IButtonProps,
  ITextFieldProps,
  ICardProps,
  IAvatarProps,
  IDialogProps,
} from '@naturacosmeticos/natds-web';

// Use in function signatures
function createButton(props: IButtonProps) {
  return <Button {...props} />;
}

Theme Typing

Using useTheme

import { useTheme } from '@naturacosmeticos/natds-web';
import type { IThemeWeb } from '@naturacosmeticos/natds-web';

function ThemedComponent() {
  const theme: IThemeWeb = useTheme();
  
  return (
    <div
      style={{
        backgroundColor: theme.palette.primary.main,
        padding: theme.spacing(2),
      }}
    >
      Themed content
    </div>
  );
}

Custom Theme Extensions

import type { IThemeWeb } from '@naturacosmeticos/natds-web';

// Extend the theme type
interface CustomTheme extends IThemeWeb {
  custom: {
    headerHeight: number;
    sidebarWidth: number;
  };
}

// Use with buildTheme
import { buildTheme } from '@naturacosmeticos/natds-web';

const customTheme: CustomTheme = {
  ...buildTheme('natura', 'light'),
  custom: {
    headerHeight: 64,
    sidebarWidth: 240,
  },
};

Event Handlers

Button Click Events

import { Button } from '@naturacosmeticos/natds-web';

function ClickableButton() {
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    event.preventDefault();
    console.log('Clicked!');
  };

  return <Button onClick={handleClick}>Click me</Button>;
}

Input Change Events

import { TextField } from '@naturacosmeticos/natds-web';

function FormInput() {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  return (
    <TextField
      label="Email"
      value={value}
      onChange={handleChange}
    />
  );
}

Select Change Events

import { Select, MenuItem } from '@naturacosmeticos/natds-web';

function SelectInput() {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setValue(event.target.value as string);
  };

  return (
    <Select value={value} onChange={handleChange}>
      <MenuItem value="option1">Option 1</MenuItem>
      <MenuItem value="option2">Option 2</MenuItem>
    </Select>
  );
}

Form Handling

Type-Safe Form State

import { TextField, Button } from '@naturacosmeticos/natds-web';

interface FormData {
  email: string;
  password: string;
}

function LoginForm() {
  const [formData, setFormData] = React.useState<FormData>({
    email: '',
    password: '',
  });

  const handleChange = (field: keyof FormData) => (
    event: React.ChangeEvent<HTMLInputElement>
  ) => {
    setFormData(prev => ({
      ...prev,
      [field]: event.target.value,
    }));
  };

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log('Form data:', formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <TextField
        label="Email"
        type="email"
        value={formData.email}
        onChange={handleChange('email')}
      />
      <TextField
        label="Password"
        type="password"
        value={formData.password}
        onChange={handleChange('password')}
      />
      <Button type="submit" variant="contained">
        Login
      </Button>
    </form>
  );
}

Ref Forwarding

import { Button } from '@naturacosmeticos/natds-web';

function ButtonWithRef() {
  const buttonRef = React.useRef<HTMLButtonElement>(null);

  React.useEffect(() => {
    if (buttonRef.current) {
      buttonRef.current.focus();
    }
  }, []);

  return <Button ref={buttonRef}>Focused Button</Button>;
}

Utility Types

Brand Types

import type { Brand } from '@naturacosmeticos/natds-react';

const brand: Brand = 'natura'; // 'natura' | 'avon' | 'theBodyShop' | 'aesop'

Theme Mode Types

type ThemeMode = 'light' | 'dark';

const mode: ThemeMode = 'dark';

TypeScript Configuration

Recommended tsconfig.json settings:
{
  "compilerOptions": {
    "target": "ES2019",
    "lib": ["ES2019", "DOM", "DOM.Iterable"],
    "jsx": "react",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  }
}

Common Patterns

Component Wrapper

import type { IButtonProps } from '@naturacosmeticos/natds-web';

interface LoadingButtonProps extends Omit<IButtonProps, 'disabled'> {
  loading: boolean;
}

function LoadingButton({ loading, children, ...props }: LoadingButtonProps) {
  return (
    <Button disabled={loading} {...props}>
      {loading ? 'Loading...' : children}
    </Button>
  );
}

Controlled Components

import { TextField } from '@naturacosmeticos/natds-web';

interface ControlledInputProps {
  value: string;
  onChange: (value: string) => void;
  label: string;
}

function ControlledInput({ value, onChange, label }: ControlledInputProps) {
  return (
    <TextField
      label={label}
      value={value}
      onChange={(e) => onChange(e.target.value)}
    />
  );
}

Best Practices

Use TypeScript’s strict mode for better type safety:
"strict": true
Use import type for type-only imports to improve tree-shaking:
import type { IButtonProps } from '@naturacosmeticos/natds-web';
Always use proper types instead of any. If needed, use unknown and narrow the type.
Let your IDE’s IntelliSense guide you - it will show all available props and their types.

Theme Types

IThemeWeb interface reference

Component Props

All component interfaces

Hooks API

TypeScript hook definitions

Styling Guide

Type-safe styling patterns

Build docs developers (and LLMs) love