Skip to main content

Quick Start

This guide will help you start using Adopta Un Abuelo React Components in your React application with practical, working examples.

Prerequisites

Before you begin, make sure you have:
  • Completed the installation steps
  • A React project (React 18+ or React 19+) with styled-components configured
  • Basic knowledge of React and TypeScript

Your First Component

Let’s start with a simple example using the ProgressBar component:
import React from 'react';
import { ProgressBar } from '@adoptaunabuelo/react-components';

function App() {
  return (
    <ProgressBar 
      maxValue={100}
      minValue={0}
      progress={40}
    />
  );
}

export default App;
This renders a progress bar at 40% completion. Simple and straightforward!

Common Components

1

Button Component

The Button component supports multiple design variants, loading states, and success animations:
import React, { useState } from 'react';
import { Button } from '@adoptaunabuelo/react-components';

function ButtonExample() {
  const [loading, setLoading] = useState(false);
  const [success, setSuccess] = useState(false);

  const handleSubmit = () => {
    setLoading(true);
    
    // Simulate API call
    setTimeout(() => {
      setLoading(false);
      setSuccess(true);
    }, 2000);
  };

  return (
    <div style={{ display: 'flex', gap: '12px' }}>
      {/* Primary button with loading state */}
      <Button 
        design="primary"
        loading={loading}
        success={success}
        onSuccess={() => setSuccess(false)}
        onClick={handleSubmit}
      >
        Submit
      </Button>

      {/* Secondary button */}
      <Button design="secondary">
        Cancel
      </Button>

      {/* Text button */}
      <Button design="text">
        Learn More
      </Button>

      {/* Small button */}
      <Button design="primary" size="small">
        Small Button
      </Button>
    </div>
  );
}
To use loading and success animations, install @lottiefiles/react-lottie-player.
2

Input Component

The Input component offers three design variants and supports all standard HTML input attributes:
import React, { useState } from 'react';
import { Input } from '@adoptaunabuelo/react-components';

function InputExample() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setEmail(e.target.value);
    
    // Simple validation
    if (e.target.value && !e.target.value.includes('@')) {
      setError('Please enter a valid email');
    } else {
      setError('');
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      {/* Secondary design (default) */}
      <Input
        design="secondary"
        type="email"
        placeholder="Enter your email"
        label="Email Address"
        value={email}
        onChange={handleChange}
        error={error}
      />

      {/* Primary design */}
      <Input
        design="primary"
        type="text"
        placeholder="Your name"
        label="Full Name"
      />

      {/* Third design */}
      <Input
        design="third"
        type="password"
        placeholder="Password"
        label="Password"
      />
    </div>
  );
}
3

Text Component

The Text component provides unified typography for headers, paragraphs, and button text:
import React from 'react';
import { Text } from '@adoptaunabuelo/react-components';
import { ColorV2 } from '@adoptaunabuelo/react-components';

function TextExample() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      {/* Headers */}
      <Text type="h1" weight="bold">
        Main Title
      </Text>
      
      <Text type="h2" weight="semibold">
        Section Heading
      </Text>
      
      <Text type="h3">
        Subsection
      </Text>

      {/* Paragraphs */}
      <Text type="p" weight="regular">
        This is regular paragraph text with normal weight.
      </Text>
      
      <Text type="p2" weight="medium">
        This is smaller paragraph text with medium weight.
      </Text>

      {/* Button text styles */}
      <Text type="b1" weight="semibold">
        Button Text Large
      </Text>
      
      <Text type="b2">
        Button Text Medium
      </Text>
    </div>
  );
}
4

Phone Input Component

The InputPhone component includes international country selection and phone validation:
import React, { useState } from 'react';
import { InputPhone } from '@adoptaunabuelo/react-components';

// Example country list - you can import from @constants/Country
const countryOptions = [
  {
    id: 'spain',
    esCountry: 'España',
    enCountry: 'Spain',
    prefix: '+34',
    countryCode: 'ES'
  },
  {
    id: 'usa',
    esCountry: 'Estados Unidos',
    enCountry: 'United States',
    prefix: '+1',
    countryCode: 'US'
  },
  {
    id: 'uk',
    esCountry: 'Reino Unido',
    enCountry: 'United Kingdom',
    prefix: '+44',
    countryCode: 'GB'
  }
];

function PhoneInputExample() {
  const [phone, setPhone] = useState('');
  const [isValid, setIsValid] = useState(false);

  const handlePhoneChange = ({ country, value, isValid }) => {
    if (isValid && value) {
      setPhone(country + value);
      setIsValid(true);
    } else {
      setIsValid(false);
    }
  };

  return (
    <div>
      <InputPhone
        design="secondary"
        country="ES"
        countryOptions={countryOptions}
        placeholder="Phone number"
        label="Phone Number"
        onPhoneChange={handlePhoneChange}
      />
      
      {isValid && (
        <Text type="p2" style={{ color: 'green', marginTop: '8px' }}>
          ✓ Valid phone number: {phone}
        </Text>
      )}
    </div>
  );
}

Complete Example Application

Here’s a complete example combining multiple components:
import React, { useState } from 'react';
import {
  Button,
  Input,
  Text,
  ProgressBar,
  Modal
} from '@adoptaunabuelo/react-components';

function CompleteExample() {
  const [step, setStep] = useState(1);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [loading, setLoading] = useState(false);
  const [showModal, setShowModal] = useState(false);

  const totalSteps = 3;
  const progress = (step / totalSteps) * 100;

  const handleNext = () => {
    if (step < totalSteps) {
      setStep(step + 1);
    } else {
      setLoading(true);
      // Simulate form submission
      setTimeout(() => {
        setLoading(false);
        setShowModal(true);
      }, 2000);
    }
  };

  const handleBack = () => {
    if (step > 1) setStep(step - 1);
  };

  return (
    <div style={{ maxWidth: '600px', margin: '0 auto', padding: '40px' }}>
      {/* Header */}
      <Text type="h1" weight="bold" style={{ marginBottom: '8px' }}>
        Welcome to Our App
      </Text>
      
      <Text type="p" style={{ marginBottom: '32px' }}>
        Complete the steps below to get started
      </Text>

      {/* Progress indicator */}
      <div style={{ marginBottom: '32px' }}>
        <Text type="p2" weight="medium" style={{ marginBottom: '12px' }}>
          Step {step} of {totalSteps}
        </Text>
        <ProgressBar
          progress={progress}
          showPercentage
          animationTime={0.5}
        />
      </div>

      {/* Step content */}
      <div style={{ marginBottom: '32px' }}>
        {step === 1 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
            <Text type="h3" weight="semibold">Personal Information</Text>
            <Input
              design="secondary"
              label="Full Name"
              placeholder="Enter your name"
              value={name}
              onChange={(e) => setName(e.target.value)}
            />
          </div>
        )}

        {step === 2 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
            <Text type="h3" weight="semibold">Contact Details</Text>
            <Input
              design="secondary"
              type="email"
              label="Email Address"
              placeholder="[email protected]"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>
        )}

        {step === 3 && (
          <div>
            <Text type="h3" weight="semibold" style={{ marginBottom: '16px' }}>
              Review Your Information
            </Text>
            <div style={{ 
              backgroundColor: '#F2F2F2', 
              padding: '16px', 
              borderRadius: '8px' 
            }}>
              <Text type="p" weight="medium">Name: {name || 'Not provided'}</Text>
              <Text type="p" weight="medium">Email: {email || 'Not provided'}</Text>
            </div>
          </div>
        )}
      </div>

      {/* Navigation buttons */}
      <div style={{ display: 'flex', gap: '12px', justifyContent: 'space-between' }}>
        <Button
          design="secondary"
          onClick={handleBack}
          disabled={step === 1}
        >
          Back
        </Button>
        
        <Button
          design="primary"
          onClick={handleNext}
          loading={loading}
          disabled={loading}
        >
          {step === totalSteps ? 'Submit' : 'Next'}
        </Button>
      </div>

      {/* Success modal */}
      {showModal && (
        <Modal
          onClose={() => {
            setShowModal(false);
            setStep(1);
            setName('');
            setEmail('');
          }}
        >
          <div style={{ padding: '32px', textAlign: 'center' }}>
            <Text type="h2" weight="bold" style={{ marginBottom: '16px' }}>
              Success!
            </Text>
            <Text type="p" style={{ marginBottom: '24px' }}>
              Your information has been submitted successfully.
            </Text>
            <Button design="primary" onClick={() => setShowModal(false)}>
              Close
            </Button>
          </div>
        </Modal>
      )}
    </div>
  );
}

export default CompleteExample;

Importing Constants

The library exports useful constants for colors and countries:
import { Color, ColorV2, Country } from '@adoptaunabuelo/react-components';

// Use predefined colors
<Button style={{ backgroundColor: Color.background.primary }}>
  Primary Color
</Button>

// Use ColorV2 for newer color system
<Text style={{ color: ColorV2.text.neutralMedium }}>
  Medium gray text
</Text>

// Access country data
<InputPhone countryOptions={Country.list} />

TypeScript Support

All components are fully typed. Take advantage of IntelliSense in your IDE:
import { Button, ButtonProps } from '@adoptaunabuelo/react-components';

// Props are fully typed
const CustomButton = (props: ButtonProps) => {
  return <Button design="primary" {...props} />;
};

Best Practices

Use Design Variants

Components offer multiple design variants (primary, secondary, text). Use them consistently throughout your app for visual hierarchy.

Handle Loading States

Use the built-in loading states for buttons and forms to provide feedback during async operations.

Validate Inputs

Leverage the error prop on input components to show validation messages.

Leverage TypeScript

Use TypeScript for better IDE support and catch errors at compile time.

Next Steps

Explore Components

Browse all components in our Storybook

View Source

Check out the source code on GitHub

Report Issues

Found a bug? Let us know

Changelog

See what’s new in each release

Need Help?

If you encounter any issues or have questions:
This library is actively maintained and used in production. We welcome contributions and feedback!

Build docs developers (and LLMs) love