---
title: "Nested Widget Descriptors"
slug: "nested-widget-descriptors"
category: "Patterns"
locale: "es"
reactExample: "pattern-descriptor.tsx"
hosts: "react"
---

# Combinar contenido y widgets en React

En los campos `ArcWidgetSlot` compatibles puedes usar texto, un elemento JSX o un descriptor de widget. Para aplicaciones React, JSX resulta práctico: props, comprobación de tipos y callbacks de eventos permanecen directamente en el componente.

## JSX y callbacks propios

```tsx
import {
  ArcWidgetBadge,
  ArcWidgetButton,
  ArcWidgetLayout,
  ArcWidgetText,
} 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;

export default function Example() {
  const [count, setCount] = useState(pack === 'busy' ? 12 : 0);
  const badges =
    pack === 'empty'
      ? []
      : [
          { value: t('Offen', 'Open', 'Abierto'), color: '#d97706' },
          { value: t('Live', 'Live', 'En vivo'), color: '#15803d' },
          ...(pack === 'busy'
            ? [
                {
                  value: t('Priorität', 'Priority', 'Prioridad'),
                  color: '#be123c',
                },
                { value: t('Messe', 'Fair', 'Feria'), color: '#7c3aed' },
              ]
            : []),
        ];
  return (
    <ArcWidgetLayout
      id="layout"
      data={{
        embedded: false,
        height: '240px',
        direction: 'vertical',
        gap: '12px',
        blocks: [
          {
            height: 'auto',
            value: (
              <ArcWidgetText
                data={{
                  value: `${t('Klicks', 'Clicks', 'Clics')}: ${count}`,
                  fontSize: '20px',
                }}
              />
            ),
          },
          ...(badges.length
            ? [
                {
                  height: 'auto' as const,
                  value: (
                    <ArcWidgetLayout
                      data={{
                        embedded: true,
                        direction: 'horizontal',
                        gap: '8px',
                        height: 'auto',
                        blocks: badges.map((badge) => ({
                          width: 'auto',
                          height: 'auto',
                          value: (
                            <ArcWidgetBadge
                              data={{
                                value: badge.value,
                                singleColor: badge.color,
                                borderRadius: '6px',
                                paddingX: '10px',
                                paddingY: '4px',
                              }}
                            />
                          ),
                        })),
                      }}
                    />
                  ),
                },
              ]
            : []),
          {
            height: 'fraction',
            value: (
              <ArcWidgetButton
                data={{
                  title: t('Weiter', 'Continue', 'Continuar'),
                  width: '160px',
                  backgroundColor: '#18181b',
                  fontColor: '#ffffff',
                }}
                onClick={() => setCount((value) => value + 1)}
              />
            ),
          },
        ],
      }}
    />
  );
}
```

`blocks[].value` pertenece a los slots compatibles. Otros ejemplos son celdas de tabla y contenidos de tarjeta. Un fragment agrupa varios contenidos de React en un solo elemento. Slideshow admite actualmente solo contenido de tipo string.

## Descriptores declarativos

Un descriptor consta de `widget`, un `id` estable opcional y `data`. `widget` usa el nombre registrado, como `arc-widget-button`. Los alias de ID antiguos `uid` y `uniqueId` se aceptan para configuraciones existentes; usa `id` para ejemplos nuevos.

```tsx
import { useState } from 'react';
import { ArcWidgetLayout } from '@arcrider/arcwidgets-react';
export default function Example() {
  const [message, setMessage] = useState('Bereit');
  return (
    <>
      <ArcWidgetLayout
        data={{
          direction: 'horizontal',
          width: '100%',
          height: '70px',
          blocks: [
            {
              width: 'fraction',
              value: {
                widget: 'arc-widget-button',
                id: 'descriptor-button',
                data: {
                  title: 'Auslösen',
                },
              },
            },
          ],
        }}
        onAction={(type) => {
          if (type === 'click') setMessage('Button angeklickt');
        }}
      />
      <p role="status">{message}</p>
    </>
  );
}
```

Aquí el descriptor usa el fallback de eventos heredado del layout. Si varios hijos interactivos deben disparar acciones distintas, usa JSX con callback props propios.

## Contenido de fuentes externas

Los slots de tipo string pueden interpretar HTML. Por eso, muestra los textos ajenos mediante JSX, por ejemplo como contenido de texto de un `span`. Usa HTML solo de fuente propia o previamente saneada. Las configuraciones de descriptor no sustituyen la validación de datos externos.

Table con mini-widgets · Dashboard.
