---
title: "¿Qué es un widget?"
slug: "was-sind-widgets"
category: "Introducción"
locale: "es"
order: 1
reactExample: "table.tsx"
hosts: "react"
---

# ¿Qué es un widget en React?

Un arcWidget es un componente configurable para una aplicación de negocio: por ejemplo una tabla, un calendario o un tablero Kanban. Pasas la representación como `data` y conectas los eventos con tu aplicación mediante callback props.

## Un ejemplo completo

```tsx
import {
  ArcWidgetBadge,
  ArcWidgetTable,
  type ArcWidgetTableRow,
} from '@arcrider/arcwidgets-react';
import { useState } from 'react';

const lang = document.documentElement.lang.startsWith('en')
  ? 'en'
  : document.documentElement.lang.startsWith('es')
    ? 'es'
    : 'de';
const requested = new URLSearchParams(location.search).get('data');
const pack = requested === 'empty' || requested === 'busy' ? requested : 'demo';
const t = (de: string, en: string, es: string) =>
  lang === 'en' ? en : lang === 'es' ? es : de;

const statusTone = {
  open: { color: '#d97706', label: t('Offen', 'Open', 'Abierto') },
  work: { color: '#0f766e', label: t('In Arbeit', 'In progress', 'En curso') },
  done: { color: '#15803d', label: t('Erledigt', 'Done', 'Hecho') },
  wait: { color: '#be123c', label: t('Wartet', 'Waiting', 'En espera') },
};

type Status = keyof typeof statusTone;
type Order = {
  id: string;
  title: string;
  amount: number;
  status: Status;
  items?: Order[];
};

const demoOrders: Order[] = [
  {
    id: 'a',
    title: t('Auftrag Nordhafen', 'North Harbor order', 'Pedido Puerto Norte'),
    amount: 240,
    status: 'work',
    items: [
      {
        id: 'a-1',
        title: t('Vorbereitung', 'Preparation', 'Preparación'),
        amount: 80,
        status: 'done',
      },
      {
        id: 'a-2',
        title: t('Umsetzung', 'Delivery', 'Entrega'),
        amount: 160,
        status: 'work',
      },
    ],
  },
  {
    id: 'b',
    title: t('Auftrag Westpark', 'Westpark order', 'Pedido Westpark'),
    amount: 80,
    status: 'open',
  },
  {
    id: 'c',
    title: t('Auftrag Innenstadt', 'Downtown order', 'Pedido centro'),
    amount: 420,
    status: 'wait',
  },
  {
    id: 'd',
    title: t('Auftrag Werkstatt', 'Workshop order', 'Pedido taller'),
    amount: 150,
    status: 'done',
  },
];

const SITES = [
  'Nordhafen',
  'Westpark',
  'Innenstadt',
  'Werkstatt',
  'Messe',
  'Logistik',
  'Campus',
  'Hafen Süd',
];
const STATUSES: Status[] = ['open', 'work', 'done', 'wait'];

const busyOrders: Order[] = Array.from({ length: 800 }, (_, index) => ({
  id: `busy-${index + 1}`,
  title: `${t('Auftrag', 'Order', 'Pedido')} ${SITES[index % SITES.length]} ${String(index + 1).padStart(3, '0')}`,
  amount: 50 + ((index * 47) % 9950),
  status: STATUSES[index % STATUSES.length],
}));

const orders =
  pack === 'empty' ? [] : pack === 'busy' ? busyOrders : demoOrders;

export default function Example() {
  const [selected, setSelected] = useState(
    t('Keine Auswahl', 'Nothing selected', 'Sin selección'),
  );
  const statusMark = (status: Status) =>
    pack === 'busy' ? (
      <span
        style={{
          display: 'inline-block',
          borderRadius: 6,
          padding: '3px 8px',
          fontSize: 12,
          fontWeight: 600,
          color: statusTone[status].color,
          backgroundColor: '#f4f4f5',
        }}
      >
        {statusTone[status].label}
      </span>
    ) : (
      <ArcWidgetBadge
        data={{
          value: statusTone[status].label,
          singleColor: statusTone[status].color,
          borderRadius: '6px',
          paddingX: '8px',
          paddingY: '3px',
        }}
      />
    );
  const row = (order: Order): ArcWidgetTableRow => ({
    id: order.id,
    clickable: true,
    columns: [
      { value: order.title, width: 'fraction' },
      {
        value: statusMark(order.status),
        width: '130px',
      },
      {
        value: order.amount,
        width: '90px',
        sort: { value: order.amount },
      },
    ],
    items: (order.items ?? []).map(row),
  });
  return (
    <>
      <ArcWidgetTable
        id="orders"
        data={{
          height: pack === 'busy' ? '520px' : '320px',
          styles: {
            borders: {
              outer: true,
              rows: true,
              columns: false,
              color: '#e4e4e7',
            },
          },
          rowHoverAction: { hoverActive: true, backgroundColor: '#fafafa' },
          header: {
            columns: [
              {
                title: t('Auftrag', 'Order', 'Pedido'),
                width: 'fraction',
                sort: { enabled: true, type: 'text' },
              },
              { title: t('Status', 'Status', 'Estado'), width: '130px' },
              {
                title: t('Betrag', 'Amount', 'Importe'),
                width: '90px',
                sort: { enabled: true, type: 'number' },
              },
            ],
          },
          table: orders.map(row),
          emptyTable: {
            title: t('Keine Aufträge', 'No orders', 'Sin pedidos'),
            value: (
              <div style={{ padding: 24, textAlign: 'center' }}>
                <strong>
                  {t('Keine Aufträge', 'No orders', 'Sin pedidos')}
                </strong>
                <p>
                  {t(
                    'Leerer Zustand — über Daten auf Voll oder Demo wechseln.',
                    'Empty state — switch Data to Full or Demo.',
                    'Estado vacío — cambia Datos a Completo o Demo.',
                  )}
                </p>
              </div>
            ),
          },
        }}
        onCellClick={(_event, { row_index }) => {
          setSelected(
            row_index == null
              ? t('Keine Auswahl', 'Nothing selected', 'Sin selección')
              : `${t('Zeile', 'Row', 'Fila')} ${row_index + 1}`,
          );
        }}
      />
      <p aria-live="polite">{selected}</p>
    </>
  );
}
```

La lista se genera a partir de datos de React. Un clic actualiza el state local. Para el acceso a datos, el almacenamiento y la navegación usas tu propia API y los componentes de tu aplicación.

## Las piezas

- `data` contiene la configuración específica del widget.
- `id` identifica opcionalmente la instancia.
- Los callback props como `onCellClick` informan las interacciones.
- Los slots de contenido permiten elementos de React propios y otros widgets.

[Configurar React](/docs/react/intro/setup-react) · [Todos los componentes](/docs/react/intro/react-components) · [Combinar componentes](/docs/react/patterns/nested-widget-descriptors).
